Thanks for your help with this. Using the technique you've suggested I've
been able to successfully add the id values with two separate XSL transform
documents, but I can't get it to work as a two-pass process in a single
stylesheet. My input file is this:
<?xml version="1.0"?>
<mytree>
<node>
<name>Root of my tree</name>
<level>0</level>
</node>
<node>
<name>Child of root</name>
<level>1</level>
</node>
<node>
<name>Another child of root</name>
<level>1</level>
</node>
<node>
<name>Grandchild of root</name>
<level>2</level>
</node>
<node>
<name>Yet another child of root</name>
<level>1</level>
</node>
</mytree>
My fisrt transform is:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:call-template name="next-level">
<xsl:with-param name="level" select="0"/>
<xsl:with-param name="nodes" select="//node"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="next-level">
<xsl:param name="level"/>
<xsl:param name="nodes"/>
<xsl:if test="$nodes/level[.=$level]">
<!-- then group the nodes at this level -->
<xsl:for-each-group select="$nodes"
group-starting-with="node[level[.=$level]]">
<!-- act on the first of each group only, passing others to next
level -->
<newnode id="">
<xsl:copy-of select="name"/>
<!-- group at the next level assuming monotonically
increasing level -->
<xsl:call-template name="next-level">
<xsl:with-param name="level" select="$level + 1"/>
<xsl:with-param name="nodes"
select="current-group()[position()>1]"/>
</xsl:call-template>
</newnode>
</xsl:for-each-group>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Which produces:
<?xml version="1.0" encoding="UTF-8"?>
<newnode id="">
<name>Root of my tree</name>
<newnode id="">
<name>Child of root</name>
</newnode>
<newnode id="">
<name>Another child of root</name>
<newnode id="">
<name>Grandchild of root</name>
</newnode>
</newnode>
<newnode id="">
<name>Yet another child of root</name>
</newnode>
</newnode>
My second transform is:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="*[@id]">
<xsl:copy>
<xsl:attribute name="id">
<xsl:number level="any" count="*[@id]"/>
</xsl:attribute>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Which when run on the intermediate result produces:
<?xml version="1.0" encoding="UTF-8"?>
<newnode id="1">
<name>Root of my tree</name>
<newnode id="2">
<name>Child of root</name>
</newnode>
<newnode id="3">
<name>Another child of root</name>
<newnode id="4">
<name>Grandchild of root</name>
</newnode>
</newnode>
<newnode id="5">
<name>Yet another child of root</name>
</newnode>
</newnode>
This is the correct result.
How do I combine these two transforms into a single stylesheet using the
two-pass approach? I can't get this to work...
Many thanks - Rowan