xslt: traverse chain of ancestors in reverse order



suppose I have the following xml-document:



<?xml version="1.0"?>
<xs:schema xmlns:xs="http://ift.tt/tphNwY">
<xs:element name="FirstLevel">
<xs:unique name="uniqueL2inL1">
<xs:selector xpath="SecondLevel" />
<xs:field xpath="@Name" />
</xs:unique>
</xs:element>
<xs:element name="SecondLevel">
<xs:unique name="uniqueL3inL2">
<xs:selector xpath="ThirdLevel" />
<xs:field xpath="@Name" />
</xs:unique>
</xs:element>
<xs:element name="ThirdLevel">
<xs:unique name="uniqueL4inL3">
<xs:selector xpath="FourthLevel" />
<xs:field xpath="@Name" />
</xs:unique>
</xs:element>
<xs:element name="FourthLevel"/>
</xs:schema>


What possibilities are there to get the "chain" of unique-definitions from the ThirdLevel element up to the document root in a backward ordering?


The resulting output I wanna have for ThirdLevel for example:



FirstLevel
SecondLevel


I got a solution which outputs them in the wrong order:



<xsl:stylesheet version="2.0"
xmlns:xsl="http://ift.tt/tCZ8VR"
xmlns:xs="http://ift.tt/tphNwY" >
<xsl:output method="text" />
<xsl:template match="xs:element">
<xsl:result-document href="chain_{@name}">
<xsl:variable name="element-name" select="@name"/>
<xsl:variable name="parent-name" select="//xs:unique/xs:selector[@xpath=$element-name]/@xpath"/>
<xsl:if test="$parent-name != ''">
<xsl:call-template name="mytemplate">
<xsl:with-param name="unique-block" select="//xs:unique/xs:selector[@xpath=$element-name]/.."/>
</xsl:call-template>
</xsl:if>
</xsl:result-document>
</xsl:template>
<xsl:template name="mytemplate">
<xsl:param name="unique-block"/>
<xsl:variable name="parent-name" select="$unique-block/../@name"/>
<xsl:value-of select="$parent-name"/>
<xsl:variable name="unique-selector" select="//xs:unique/xs:selector[@xpath=$parent-name]/@xpath"/>
<!-- evaluate and recurse, if needed: -->
<xsl:if test="$unique-selector != ''">
<xsl:call-template name="mytemplate">
<xsl:with-param name="unique-block" select="//xs:unique/xs:selector[@xpath=$parent-name]/.." />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>


Which outputs:



saxonb-xslt -ext:on -s:minimal.xsd -xsl:minimal.xslt && cat chain_ThirdLevel

SecondLevel
FirstLevel


But the approach itself feels just wrong to me... Some tips or improvements?


Greetings


No comments:

Post a Comment