Re: [xsl] Variable as Position Indicator

Subject: Re: [xsl] Variable as Position Indicator
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Thu, 4 Jan 2001 09:53:48 +0000
Hi Mark,

> The following code creates a variable that can be used to select a
> specific section. When testing the code, the $nextPage variable
> prints correctly (for testing), but when it is placed as an index to
> the section tag, it always reverts to the number '1'.

When you create your two variables, you're using the *content* of the
xsl:variable element to give the value of the variable:

<xsl:variable name="currentPage"><xsl:number/></xsl:variable>
<xsl:variable name="nextPage">
   <xsl:value-of select="$currentPage + 1"/>
</xsl:variable>

When you use the content of a variable to give a value, then it
actually creates a little node tree (called a result tree fragment)
with a root node and whatever you have as the content of the variable
as the content of the result tree fragment. The variable itself
actually holds a pointer to the root node in this result tree
fragment. In your case, the $currentPage variable is set to (the root
node of) a result tree fragment whose root node has a single child: a
text node with a value given by <xsl:number />.

When you get the value of (the root node of) such a result tree
fragment, just like if you get the value of (the root node of) a XML
document, you get a string made up of all the text nodes in the result
tree fragment. So the value of (the root node) $currentPage is a
string of the number that you've used.

The $nextPage variable is set to (the root node of) a result tree
fragment whose root node again has a single text node as a child. The
value of the text node is given as the $currentPage plus one. Remember
that $currentPage is a result tree fragment?  In this context it will
be coerced into a number because it's being used in a numerical
expression.  So $nextPage's text node ends up being the right number.

Now, you use the $nextPage variable to index into the list of
sections:

<xsl:value-of select="//section[$nextPage]/@subject"/>.html

Remember that the $nextPage variable is set to (the root node of) a
result tree fragment? Well, here it matters. Within a predicate,
everything but a number is coerced to a boolean. When you coerce (the
root node of) a result tree fragment to a boolean, you *always* get
the result true() because there is *always* (a root node of) a result
tree fragment. As it's always true, all the sections are returned,
which means all their subjects are returned by the expression. Taking
the value of that node set involves getting the value of the first
node of the node set, so you always get the subject of the first
section.

You wanted to make $nextPage be treated as a number, and so give an
index into the sections.  You can do this in two ways.  First, you can
expand the expression so that you're testing the position() of the
section against the value of the $nextPage variable:

  //section[position() = $nextPage]/@subject

Secondly, you can explicitly coerce the $nextPage variable to be a
number, so that it's interpreted as an index:

  //section[number($nextPage)]/@subject

These solutions will both work, but a third solution would probably be
better.  Whenever you can, rather than setting a variable to a result
tree fragment, you should make it a string, number or boolean or
whatever you *actually* want to it be.  You can do this by using the
select attribute to set the value of the variable rather than the
content.  If you'd set the value for $nextPage using the expression:

<xsl:variable name="nextPage" select=" $currentPage + 1"/>

then $nextPage is actually set to that *number*, so you don't have to
coerce it at all and your original expression:

  //section[$nextPage]/@subject

will work.

[Aside: I use (the root node of) a lot in the above because we're in a
state of flux regarding the status of variables set using their
content.  In XSLT 1.0 they're result tree fragments, treated
specially, but in XSLT 1.1 they're created node sets and it starts
being helpful to think of the variables as referencing the root node
of these node sets rather than holding an inviolable entity.]
  
I hope that helps,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread