tags:

views:

76

answers:

4

IS there any way to use XSLT to generate unique IDs (sequential is fine) when they don't already exist? I have the following:

<xsl:template match="Foo">
   <xsl:variable name="varName">
      <xsl:call-template name="getVarName">
         <xsl:with-param name="name" select="@name"/>
      </xsl:call-template>
   </xsl:variable>
   <xsl:value-of select="$varName"/> = <xsl:value-of select="@value"/>
</xsl:template>

<xsl:template name="getVarName">
   <xsl:param name="name" select="''"/>
   <xsl:choose>
      <xsl:when test="string-length($name) > 0">
         <xsl:value-of select="$name"/>
      </xsl:when>
      <xsl:otherwise>
         <xsl:text>someUniqueID</xsl:text> <!-- Stuck here -->
      </xsl:otherwise>
   </xsl:choose>
</xsl:template>

With an input of something like:

<Foo name="item1" value="100"/>
<Foo name="item2" value="200"/>
<Foo value="300"/>

I'd like to be able to assign a unique value so that I end up with:

item1 = 100
item2 = 200
unnamed1 = 300
A: 

Case 5 of http://www.dpawson.co.uk/xsl/sect2/N4598.html might get you along.

Obalix
+1  A: 

Maybe appending your own constant prefix to the result of generate-id function will do the trick?

GSerg
A: 

Try something like this instead of your templates:

<xsl:template match="/DocumentRootElement">
<xsl:for-each select="Foo">
  <xsl:variable name="varName">
    <xsl:choose>
      <xsl:when test="string-length(@name) > 0">
        <xsl:value-of select="@name"/>
      </xsl:when>
      <xsl:otherwise>unnamed<xsl:value-of select="position()"/></xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  <xsl:value-of select="$varName"/> = <xsl:value-of select="@value"/>\r\n
</xsl:for-each>

Dmitry Tashkinov
+2  A: 

First off, the context node does not change when you call a template, you don't need to pass a parameter in your situation.

<xsl:template match="Foo">
   <xsl:variable name="varName">
      <xsl:call-template name="getVarName" />
   </xsl:variable>
   <xsl:value-of select="$varName"/> = <xsl:value-of select="@value"/>
</xsl:template>

<xsl:template name="getVarName">
   <xsl:choose>
      <xsl:when test="@name != ''">
         <xsl:value-of select="@name"/>
      </xsl:when>
      <xsl:otherwise>
         <!-- position() is sequential and  unique to the batch -->
         <xsl:value-of select="concat('unnamed', position())" />
      </xsl:otherwise>
   </xsl:choose>
</xsl:template>

Maybe this is all you need right now. The output for unnamed nodes will not be strictly sequentially numbered (unnamed1, unnamed2, etc), though. You would get this:

item1 = 100
item2 = 200
unnamed3 = 300
Tomalak
This worked beautifully, thanks!
Jon