views:

24

answers:

1

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.

+2  A: 

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>
DevNull
Worked perfectly! I see now how generate-id always resolves to the same id for a given element. Thank you.
DJC
Good answer (+1)
Dimitre Novatchev
You're welcome DJC. Thank you Dimitre!
DevNull