Это более простое и эффективное решение XSLT 1.0, чем подсчет всех предыдущих братьев и сестер :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kFollowing" match="item"
use="generate-id(preceding-sibling::header[1])"/>
<xsl:template match="/*">
<root>
<xsl:apply-templates select="header"/>
</root>
</xsl:template>
<xsl:template match="header">
<heather2>
<xsl:copy-of select="key('kFollowing', generate-id())"/>
</heather2>
</xsl:template>
</xsl:stylesheet>
Когда это преобразование применяется к следующему документу XML :
<root>
<header/>
<item>1</item>
<item>2</item>
<item>3</item>
<header/>
<item>5</item>
<item>6</item>
<item>7</item>
</root>
желаемый, правильный результат получен :
<root>
<heather2>
<item>1</item>
<item>2</item>
<item>3</item>
</heather2>
<heather2>
<item>5</item>
<item>6</item>
<item>7</item>
</heather2>
</root>
Пояснение :
Ключопределяется таким образом, что для header
любой из следующих непосредственно за item
элементов соответствует generate-id()
этого header
.
II.Решение XSLT 2.0 :
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<root>
<xsl:for-each-group select="item"
group-adjacent=
"generate-id(preceding-sibling::header[1])">
<header2>
<xsl:sequence select="current-group()"/>
</header2>
</xsl:for-each-group>
</root>
</xsl:template>
</xsl:stylesheet>
, когда это преобразование применяется к тому же XML-документу (см. Выше), получается тот же правильный результат :
<root>
<header2>
<item>1</item>
<item>2</item>
<item>3</item>
</header2>
<header2>
<item>5</item>
<item>6</item>
<item>7</item>
</header2>
</root>
Пояснение : Использование xsl:for-each-group
, group-adjacent
, current-group()