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:
when this transformation is applied on the provided XML document (corrected to be well-formed):
the wanted result is produced:
Do note: The use of keys makes this transformation many times faster (in case of many
alert
siblings) than using thepreceding-sibling::
orfollowing-sibling::
axes.Besides Dimitre's good answer (probably the clasic solution for this kind of problems), this stylesheet:
Output:
Note: This use fine grained trasversal.
Edit: Better pattern matching with modes.
If you are using XSLT 2 something like the following should work: