Search code examples
xsltxslt-2.0saxonxsl-variable

Get element values in xsl:variable


Please forgive my ignorance of XSLT I'm fairly new to it.

Using saxon xslt 2.0: I'm trying to get a single element from an xsl:variable that looks like this when applying <xsl:copy-of select="$type">:

  <type>
     <label>Book</label>
     <id>book</id>
  </type>

Trying to access the id element only - I've attempted:

<xsl:copy-of select="$type/id">
<xsl:copy-of select="$type[2]">
<xsl:value-of select="$type/id">
<xsl:value-of select="$type[2]">

Also tried this and a few variants as well

<xsl:value-of select="$type[name()='id']"/>

And tried changing the data type

<xsl:variable name="type" as="element"> 

With XSLT 2.0 node-set() manipulations don't seem to apply.

I seek a detailed description of how to properly access xsl:variable elements and would also be happy to find I'm using this all wrong there's a better way. Thank you for your insights and efforts.

@martin-honnen When adding:

<xsl:variable name="test1">
  <type>
     <label>Book</label>
     <id>book</id>
  </type>
</xsl:variable>

<TEST1><xsl:copy-of select="$test1/type/id"/></TEST1>

<xsl:variable name="test2" as="element()">
  <type>
     <label>Book</label>
     <id>book</id>
  </type>
</xsl:variable>

<TEST2><xsl:copy-of select="$test2/id"/></TEST2>

I get the result:

   <TEST1/>
   <TEST2/>

Solution

  • If you have

    <xsl:variable name="type">
      <type>
         <label>Book</label>
         <id>book</id>
      </type>
    </xsl:variable>
    

    then you need e.g. <xsl:copy-of select="$type/type/id"/> to copy the id element as the type variable is bound to a temporary document node containing a type element node with an id child element node.

    Or use

    <xsl:variable name="type" as="element()">
      <type>
         <label>Book</label>
         <id>book</id>
      </type>
    </xsl:variable>
    

    then <xsl:copy-of select="$type/id"/> works, as now the variable is bound to the type element node.

    Here is a complete sample with my suggestions:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    
    <xsl:output indent="yes"/>
    
    <xsl:template match="/">
    
    <xsl:variable name="test1">
      <type>
         <label>Book</label>
         <id>book</id>
      </type>
    </xsl:variable>
    
    <TEST1><xsl:copy-of select="$test1/type/id"/></TEST1>
    
    <xsl:variable name="test2" as="element()">
      <type>
         <label>Book</label>
         <id>book</id>
      </type>
    </xsl:variable>
    
    <TEST2><xsl:copy-of select="$test2/id"/></TEST2>
    
    </xsl:template>
    
    </xsl:stylesheet>
    

    output is

    <TEST1>
       <id>book</id>
    </TEST1>
    <TEST2>
       <id>book</id>
    </TEST2>