Diese Umwandlung :
<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:variable name="Lower" select=
"'abcdefghijklmnopqrstuvwxyz'"
/>
<xsl:variable name="vUpper" select=
"'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"
/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<root>
<xsl:apply-templates select="node()"/>
<xsl:apply-templates select="/*/*//*" mode="extract">
<xsl:sort select="count(ancestor::*)" data-type="number"/>
</xsl:apply-templates>
</root>
</xsl:template>
<xsl:template match="*[ancestor::*[2]]">
<xsl:variable name="vPos">
<xsl:number level="any"/>
</xsl:variable>
<xsl:element name="{name()}">
<xsl:attribute name="ref">
<xsl:value-of select=
"concat(translate(name(),$vUpper,$Lower),$vPos)"/>
</xsl:attribute>
</xsl:element>
</xsl:template>
<xsl:template match="*" mode="extract">
<xsl:variable name="vPos">
<xsl:number level="any"/>
</xsl:variable>
<xsl:element name="{name()}">
<xsl:attribute name="id">
<xsl:value-of select=
"concat(translate(name(),$vUpper,$Lower),$vPos)"/>
</xsl:attribute>
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
bei Anwendung auf das bereitgestellte XML-Dokument :
<root>
<A>
<B att="val">
<C>
someData
</C>
</B>
</A>
<A>
<B>
someOtherData
</B>
<B>
moreData
</B>
</A>
</root>
produziert genau das gewünschte, richtige Ergebnis :
<root>
<A>
<B ref="b1"/>
</A>
<A>
<B ref="b2"/>
<B ref="b3"/>
</A>
<B id="b1" att="val">
<C ref="c1"/>
</B>
<B id="b2">
someOtherData
</B>
<B id="b3">
moreData
</B>
<C id="c1">
someData
</C>
</root>
Die umgekehrte Transformation ist :
<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="kElbyId" match="*" use="@id"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[@ref]">
<xsl:apply-templates mode="deepen"
select="key('kElbyId',@ref)"/>
</xsl:template>
<xsl:template match="*[@id]"/>
<xsl:template match="*[@id]" mode="deepen">
<xsl:copy>
<xsl:apply-templates
select="@*[not(name()='id')] | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Wenn diese umgekehrte Transformation auf das Ergebnis der obigen Glättungstransformation angewendet wird, entsteht das ursprüngliche XML-Dokument :
<root>
<A>
<B att="val">
<C>
someData
</C>
</B>
</A>
<A>
<B>
someOtherData
</B>
<B>
moreData
</B>
</A>
</root>