В XSLT-2.0 это легко:
<xsl:template match="containers">
<xsl:copy>
<xsl:for-each-group select="container" group-adjacent="@type">
<xsl:for-each select="current-group()">
<container>
<xsl:copy-of select="@*" />
<xsl:attribute name="class"><xsl:value-of select="position()-1" /></xsl:attribute>
</container>
</xsl:for-each>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
Его вывод:
<?xml version="1.0" encoding="UTF-8"?>
<containers>
<container type="1" class="0"/>
<container type="2" class="0"/>
<container type="2" class="1"/>
<container type="1" class="0"/>
<container type="2" class="0"/>
<container type="2" class="1"/>
<container type="2" class="2"/>
</containers>
Решение XSLT-1.0 это (вдохновлено этим Ответ SO ):
<xsl:template match="containers">
<xsl:copy>
<xsl:for-each select="container">
<container>
<xsl:copy-of select="@*" />
<xsl:attribute name="class"><xsl:value-of select="count(preceding-sibling::container) - count(preceding-sibling::container[@type!=current()/@type][1]/preceding-sibling::container | preceding-sibling::container[@type!=current()/@type][1])" /></xsl:attribute>
</container>
</xsl:for-each>
</xsl:copy>
</xsl:template>
Это сложнее и медленнее - и гораздо менее элегантно. Но это делает свою работу. Выход такой же.