@ empo ответ работает только в очень простых случаях, а не с таким XML-документом, как этот :
<root>
<c>
<d></d>
<e>
<f></f>
</e>
<b></b>
<b></b>
<b></b>
</c>
<b></b>
<b></b>
</root>
Здесь, если мы хотим обернуть каждую группу последовательных b
с в a
, один из способов добиться этого - :
<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="b"
use="generate-id(preceding-sibling::*[not(self::b)][1])"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="b[not(preceding-sibling::*[1][self::b])]">
<a>
<xsl:copy-of select=
"key('kFollowing', generate-id(preceding-sibling::*[1]))"/>
</a>
</xsl:template>
<xsl:template match="b"/>
</xsl:stylesheet>
когда это преобразование применяется к вышеуказанному XML-документу, требуемый правильный результат (все группы последовательных b
s заключены в a
), получается :
<root>
<c>
<d/>
<e>
<f/>
</e>
<a>
<b/>
<b/>
<b/>
</a>
</c>
<a>
<b/>
<b/>
</a>
</root>