[xsl] Context document with exsl:node-set()?

Subject: [xsl] Context document with exsl:node-set()?
From: "Scott Trenda" <Scott.Trenda@xxxxxxxx>
Date: Thu, 1 Nov 2007 13:05:45 -0500
What happens to the context document when you use this in XSLT 1.0?

<xsl:variable name="some-variable">
  <xsl:call-template name="get-some-complex-set-of-nodes"/>
</xsl:variable>
<xsl:apply-templates select="exsl:node-set($some-variable)"/>

In my stylesheet where I'm encountering this problem, I have a set of
flat data that I'm structuring into a tree. After that, I'm sorting the
structured data (have to sort branch and leaf nodes at the same level,
based on descendant-or-self::leaf/@id), and have to take into account an
ordering-configuration list elsewhere in the original document, linked
with leaf/@id. I have a key set up to do so, but when I
<xsl:apply-templates select="exsl:node-set($structured-data)"
mode="tree-sort"/>, the tree-sort templates aren't finding the data I
originally pointed to with the keys. My suspicions are that the context
document changes to the contents of $structured-data when I
apply-templates to it, and the key's target data doesn't exist there. Am
I thinking correctly on this one? And if so, are new context documents
only created when the variable has template content?


Example document:
<root>
  <ordering-configuration>
    <leaf id="1" sorted-position="6"/>
    <leaf id="2" sorted-position="1"/>
    <leaf id="3" sorted-position="4"/>
    <leaf id="4" sorted-position="3"/>
    <leaf id="5" sorted-position="2"/>
    <leaf id="6" sorted-position="5"/>
  </ordering-configuration>
  <seeds>
    <branch id="b1"/>
    <branch id="b2" branch="b1"/>
    <leaf/>
    <leaf/>
    <leaf branch="b2"/>
    <leaf branch="b2"/>
    <leaf branch="b1"/>
    <leaf branch="b1"/>
  </seeds>
</root>

Expected output:
<root>
  <leaf id="2"/>
  <branch id="b1">
    <leaf id="5"/>
    <branch id="b2">
      <leaf id="4"/>
      <leaf id="3"/>
    </branch>
    <leaf id="6"/>
  </branch>
  <leaf id="1"/>
</root>

Example stylesheet:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:exsl="http://exslt.org/common"; exclude-result-prefixes="exsl">
  <xsl:key name="children" match="branch|leaf" use="@branch"/>
  <xsl:key name="parents" match="branch" use="@id"/>

  <xsl:variable name="order-config"
select="/root/ordering-configuration/leaf"/>
  <xsl:variable name="tree">
    <xsl:variable name="sprout">
      <xsl:apply-templates select="(//branch|//leaf)[not(key('parents',
@branch))]" mode="tree-build"/>
    </xsl:variable>
    <xsl:apply-templates select="exsl:node-set($sprout)"
mode="tree-sort"/>
  </xsl:variable>

  <xsl:template match="branch" mode="tree-build">
    <branch id="{@id}">
      <xsl:apply-templates select="key('children', @id)"
mode="tree-build"/>
    </branch>
  </xsl:template>
  <xsl:template match="leaf" mode="tree-build">
    <leaf id="{count(preceding-sibling::leaf|.)}"/>
  </xsl:template>

  <xsl:template match="/|branch|leaf" mode="tree-sort">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="branch|leaf" mode="tree-sort">
        <xsl:sort select="$order-config[@id =
current()/descendant-or-self::leaf/@id]/@sorted-position"
data-type="number"/>
        <xsl:sort select="descendant-or-self::leaf/@id"
data-type="number"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="root">
    <root>
      <!-- there's a whole lot more complex processing here in the
non-example stylesheet that warrants the use of $tree -->
      <xsl:copy-of select="$tree"/>
    </root>
  </xsl:template>

</xsl:stylesheet>

... Would that first <xsl:sort> work for the situation I described? I'd
originally set up the key so that I could just pass it @id without
worrying about the XPath's context node, but if
/root/ordering-configuration/leaf[@id =
current()/descendant-or-self::leaf/@id]/@sorted-position will return a
node-set that will sort based on its smallest node, then that's what I'm
looking for.

I might have answered my own question there, but I'd still like to know
what to expect when applying templates to variable content.


~ Scott

Current Thread