RE: [xsl] constructing the Node Sets

Subject: RE: [xsl] constructing the Node Sets
From: "Roger Glover" <glover_roger@xxxxxxxxx>
Date: Thu, 30 Jan 2003 00:46:20 -0600
David Carlisle wrote:

> > Well, except possibly for order, as I noted earlier.
> Not at all.  Node sets are sets and as such have no ordering property.

I WAS ABSOLUTELY WRONG.  I have been mistakenly considering the following to
be XPath node sets:
    o   a "current node list" (which is an XSLT concept, not an
        XPath concept)
    o   several different XPath expression concepts, including but
        not limited to:
        o   "AbsoluteLocationPath"
        o   "RelativeLocationPath"
        o   "Step"
        each of which alone may be a "PathExpr" which would evaluate
        to a node set, but in the cases that were confusing me were
        just pieces of larger expressions that were not yet node sets.

Each of these concepts has the qualities, especially with regard to order
and "position()", which I was mistakenly ascribing to node sets.

> If two node sets have the same members they are indistinguishable in
> Xpath.

Much to my surprise, this was certainly true with every node-set-valued
XPath expression I attempted to check this out.  Eventually I understood how
this worked except for one case that puzzled me all afternoon:

For this XML:
-----------------------
<a>
    <b/>
    <c>1</c>
    <c>2</c>
    <c>3</c>
    <c>4</c>
    <d/>
</a>
-----------------------

And this XSLT:
-----------------------
<xsl:transform version="1.1"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

<xsl:output method="text"/>

<xsl:template match="/a">
	<xsl:apply-templates select="d"/>
</xsl:template>

<!-- THE FOLLOWING IS THE INTERESTING TEMPLATE -->
<xsl:template match="d">
	<xsl:for-each select="preceding::c[1]">
	    <xsl:apply-templates select="."/>
	</xsl:for-each>
	<xsl:text>&#xA;</xsl:text>
	<xsl:for-each select="(preceding::c)[1]">
	    <xsl:apply-templates select="."/>
	</xsl:for-each>
</xsl:template>

<xsl:template match="*">
	<xsl:value-of select="name()"/>
	<xsl:text>: </xsl:text>
	<xsl:value-of select="."/>
	<xsl:text>&#xA;</xsl:text>
</xsl:template>

</xsl:transform>
-----------------------

I was seeing this output:
-----------------------
c: 4

c: 1
-----------------------

The result for the first "c" expression, "preceding::c[1]", was exactly what
I expected based on the specification for the "preceding" axis.  The second
"c" expression, "(preceding::c)[1]", had me banging my head against the wall
and scrambling frantically throught the specification for an explanation.
Surely "preceding::c" and "(preceding::c)" represented the same node set,
right?  So how can they behave so differently when the predicate, "[1]", is
attached?  Eventually, I discovered the distinction between a
RelativeLocationPath and a FilterExpr.

"preceding::c" is a Step, which, when viewed as a collection of nodes, has
order behavior characteristic of the AxisSpecifier "preceding::", which is
*reverse* document order (right-(bottom-)first, post-order tree traversal).
Also, since there is a predicate attached, the Step is not yet evaluated as
a node set.  That happens only when the complete expression, the
RelativeLocationPath "preceding::c[1]", is evaluated as a PathExpr.  Thus,
the predicate indexes the first "c" element immediately preceding the "d"
element.

"(preceding::c)" is a PrimaryExpr, which, because it contains a Step
evaluates as an intermediate node set.  When attached to the predicate the
whole thing, "(preceding::c)[1]", is a FilterExpr.  At this point in the
expression evaluation the collection of nodes in the node set acquires the
order behavior characteristic of FilterExpr, which is "document order"
(left-(top-)first, pre-order tree traversal).  This FilterExpr is now
evaluates as a "PathExpr".  Thus, the predicate indexes the first "c"
element found looking down the list of all "c" elements that precede the "d"
element.

It still seems passing strange to me that "preceding::c[1]" should give
different results than "(preceding::c)[1], but at least now, after only 4
hours of study and an hour of writing this message, I understand why.

I think I'll be quiet and listen for a while now.

-- Roger Glover
   glover_roger@xxxxxxxxx




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


Current Thread