Referencing inserted elements in a single pass
-
26-09-2019 - |
Question
I'm trying to insert unique IDs and references to those IDs using a single XSLT file.
Given the XML:
<Parent>
<Name>Dr Evil</Name>
<Child>
<Name>Scott Evil</Name>
</Child>
</Parent>
And this XSLT snippet after an identity transform:
<xsl:template match="Parent">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:element name="UID"><xsl:value-of select="generate-id(.)"/></xsl:element>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="Child">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:element name="UID"><xsl:value-of select="generate-id(.)"/></xsl:element>
<xsl:element name="ParentUID"><xsl:value-of select="../UID"/></xsl:element>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
I get the output:
<Parent>
<UID>XYZ123</UID>
<Name>Dr Evil</Name>
<Child>
<UID>ABC789</UID>
<ParentUID/> <-- expected <ParentUID>XYZ123</ParentUID>
<Name>Scott Evil</Name>
</Child>
</Parent>
In other words, the UID element being inserted into the Parent isn't visible when the ParentUID element is being inserted into the Child.
I know that I could use two passes (two transforms) but I'm really keen to try and do this in one file.
Solution
Try changing your parentUID
element to:
<xsl:element name="ParentUID">
<xsl:value-of select="generate-id(parent::Parent)"/>
</xsl:element>
You can also remove the xsl:element
:
<ParentUID><xsl:value-of select="generate-id(parent::Parent)"/></ParentUID>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow