Using xslt to interpret the flat xml in the nested xhtml
source link: https://www.codesd.com/item/using-xslt-to-interpret-the-flat-xml-in-the-nested-xhtml.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Using xslt to interpret the flat xml in the nested xhtml
I am attempting to write XSLT that will select immediate-siblings of a certain type, but stop when a different tag is reached.
Here's the Source XML:
<?xml version="1.0"?>
<body>
<proc>Test</proc>
<alert>Test1: alert 1</alert>
<alert>Test1: alert 2</p>
<para>Test para 1</para>
<alert>Test2: alert 1</alert>
<alert>Test2: alert 2</alert>
<alert>Test2: alert 3</alert>
<proc>Test</proc>
<alert>Test3: alert 1</alert>
<alert>Test3: alert 2</alert>
<alert>Test3: alert 3</alert>
</html>
Here's the expected result:
<?xml version="1.0" encoding="UTF-8"?>
<body>
<proc>
<alert>Test1: alert 1</alert>
<alert>Test1: alert 2</alert>
</proc>
<para>Test para 1</para>
<alert>Test2: alert 1</alert>
<alert>Test2: alert 2</alert>
<alert>Test2: alert 3</alert>
<proc>
<alert>Test3: alert 1</alert>
<alert>Test3: alert 2</alert>
<alert>Test3: alert 3</alert>
</proc>
</body>
is this even possible?
Here's my current xsl which isn't doing the trick:
<xsl:template match="proc">
<xsl:variable name="procedure" select="."/>
<xsl:apply-templates/>
<xsl:for-each
select="following-sibling::alert[preceding-sibling::proc[1] = $procedure]">
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:template>
<xsl:template match="c:hhtAlert">...</xsl:template>
<xsl:template match="c:hhtPara">...</xsl:template>
Here is an efficient and quite short XSLT 1.0 solution:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kFollowing" match="alert"
use="generate-id(preceding-sibling::*
[
self::proc
or
self::para
]
[1]
[self::proc]
)"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="proc">
<proc>
<xsl:apply-templates select="key('kFollowing', generate-id())" mode="copy"/>
</proc>
</xsl:template>
<xsl:template match="alert" mode="copy">
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template match="alert[preceding-sibling::*
[
self::proc
or
self::para
]
[1]
[self::proc]
]"
/>
</xsl:stylesheet>
when this transformation is applied on the provided XML document (corrected to be well-formed):
<body>
<proc>Test</proc>
<alert>Test1: alert 1</alert>
<alert>Test1: alert 2</alert>
<para>Test para 1</para>
<alert>Test2: alert 1</alert>
<alert>Test2: alert 2</alert>
<alert>Test2: alert 3</alert>
<proc>Test</proc>
<alert>Test3: alert 1</alert>
<alert>Test3: alert 2</alert>
<alert>Test3: alert 3</alert>
</body>
the wanted result is produced:
<body>
<proc>
<alert>Test1: alert 1</alert>
<alert>Test1: alert 2</alert>
</proc>
<para>Test para 1</para>
<alert>Test2: alert 1</alert>
<alert>Test2: alert 2</alert>
<alert>Test2: alert 3</alert>
<proc>
<alert>Test3: alert 1</alert>
<alert>Test3: alert 2</alert>
<alert>Test3: alert 3</alert>
</proc>
</body>
Do note: The use of keys makes this transformation many times faster (in case of many alert
siblings) than using the preceding-sibling::
or following-sibling::
axes.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK