Search code examples
variablesxslt-1.0node-set

XSLT create node name from variable


When I have these two variables

<xsl:variable name="a" select="'Total'" />
<xsl:variable name="b" select="'500'" />

I would like create a node with the name of variable 'a' and its content from variable 'b'. I have to use xsltproc with XSLT 1.0 and a couple of EXSLT extensions (node-set amongst them) so I have kind of achieved part of it:

<xsl:template match="/">
  <xsl:variable name="x" >
    &lt;<xsl:value-of  select="$a" />&gt;
        <xsl:value-of  select="$b" />
    &lt;/<xsl:value-of  select="$a" />&gt;
  </xsl:variable>
  <xsl:value-of disable-output-escaping="yes" select="$x" />
</xsl:template>

indeed puts out this (I don't care about whitespace for the moment):

<?xml version="1.0"?>

    <Total>
        500
    </Total>

But: I want to use variable 'x' as a node set in order to further manipulate it (of course my real life example is more complex). What I did was transform it into a node-set (using exslt.org/common), that seems to work but accessing the contents does not.

  <xsl:variable name="nodes" select="common:node-set($x)" />
  <xsl:value-of select="$nodes/Total" />

leads to nothing. I would have expected '500' since $nodes/Total should be a valid XPATH 1.0 expression. Obviously I'm missing something. I guess the point is that the dynamic creation of the node name with &lt;...&gt; does not really create a node but just some textual output so how can I achieve a true node creation here?


Solution

  • This transformation:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:variable name="a" select="'Total'" />
     <xsl:variable name="b" select="'500'" />
    
    
     <xsl:template match="/*">
      <xsl:variable name="rtfX">
        <xsl:element name="{$a}">
          <xsl:value-of select="$b"/>
        </xsl:element>
      </xsl:variable>
    
      <xsl:value-of select="ext:node-set($rtfX)/Total"/>
     </xsl:template>
    </xsl:stylesheet>
    

    when applied on any XML document (not used), produces the wanted, correct result:

    500