Extract Last Node in Variable

deleyd
deleyd used Ask the Experts™
on
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml"/>

  <xsl:template match="/">
    <html>
      <body>
      <xsl:variable name="v">
        <xsl:call-template name="HelloWorld"/>
      </xsl:variable>
      <xsl:variable name="x" select="v/*[position() != last()]"/>
      <xsl:copy-of select="$x"/>          
        </body>
    </html>
  </xsl:template>

  <xsl:template name="HelloWorld">
    <p>Hello world!</p>
    <xsl:text>5</xsl:text>
  </xsl:template>
  
</xsl:stylesheet>

Open in new window

I'm trying to strip off the "5" which is appended to the end. My desired output is
<?xml version="1.0" encoding="utf-8"?><html><body><p>Hello world!</p></body></html>

Open in new window

and I would also like to get that "5" into a variable.

The debugger shows variable v is:

Debugger outputand variable x is empty (my select isn't working).

Update: I see I forgot the $. Change that line to:
<xsl:variable name="x" select="$v/*[position() != last()]"/>

Open in new window

and now I get an exception which says, "To use a result tree fragment in a path expression, first convert it to a node-set using the msxsl:node-set()". Great. (I actually used to know this stuff a few years ago! I've forgotten it all! How do I convert this to a node-set?)
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Gertone (Geert Bormans)Information Architect
Top Expert 2006

Commented:
XSLT1 copies bits and pieces into a result tree
You can build a part of that output tree as a result tree fragment in a variable,
but you can only copy that, but not XPath it

using the node-set() function

put this namespace in the stylesheet element
xmlns:msxsl="urn:schemas-microsoft-com:xslt"

then you can transform the result tree fragment into a node-set with the extension function msxsl:node-set() and execute an XPath on the node-set
select="msxsl:node-set($v)/*[position() != last()]

Each XSLT1 processor had a variant of the node-set() function, but it caused code to become vendor specific
XSLT2 fixed this by allowing nodesets in variables and address them
so, my next hint to explore Saxon .net ;-)
Information Architect
Top Expert 2006
Commented:
I do prefer
select="msxsl:node-set($v)/*[not(position() = last())]
to avoid the surprises of '=' being a set compare

Your example is a bit artificial... I try to avoid working on variables like this, by constructing better XPaths along teh way
but that is hard to demonstrate on this artificial example

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial