RE: [xsl] xsl:number with level=any

Subject: RE: [xsl] xsl:number with level=any
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Wed, 13 Oct 2004 18:03:20 +0100
There are some known difficulties with the XSLT 1.0 specification here, for
example (a) the question of whether the result can be zero in the case where
the current node does not match the "count" pattern, and (b) what happens
when nothing matches the "from" pattern. The 2.0 spec attempts to clarify
the rules that apply here.

But the 1.0 spec does say explicitly that the "from" node is the last node
*before* the current node that matches the "from" pattern, which means that
it is irrelevant whether or not the current node matches the "from" pattern.
In the case where no node before the current node matches the "from"
pattern, my interpretation (and that of the 2.0 spec) is that you count all
the nodes back to the root.

This justifies the Saxon 6.x result:

<doc>
<x count="1">
 <x count="1"/>
 <x count="2"/>
</x>
</doc>

For the first x node, there is no x before the current node that matches the
"from" pattern, so it is counting all x nodes back to the root; for the
second and third x nodes, the "from" node is the first x, so it counts all
the x elements after the "from" node up to and including the current node.

The XSLT 2.0 specification was written as a best attempt to formalize the
XSLT 1.0 rules, resolving ambiguities but not changing the intent for cases
that were well-defined. In this case, however, it does seem to give a
different answer. In fact, I think it is internally inconsistent. It says:

<quote>
Let $F be the node sequence selected by the expression

   $S/(preceding::node()|ancestor-or-self::node())[matches-from(.)][last()]

(the last node in document order that matches the from pattern and that
precedes the selected node, using the same definition)
</quote>

but the XPath expression given is capable of matching the selected node $S,
so it disagrees with the text in parentheses that follows. I think that the
text represents the true intent (which was to retain the 1.0 behavior where
it was well-defined), which means that the expression should be changed to

$S/(preceding::node()|ancestor::node())[matches-from(.)][last()]

and this I believe would give the same result as Saxon is giving.

Michael Kay


> -----Original Message-----
> From: Richard Tobin [mailto:richard@xxxxxxxxxxxx] 
> Sent: 13 October 2004 01:42
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] xsl:number with level=any
> 
> How exactly should the number be calculated in xsl:number 
> when level=any?
> In particular, are the context node and the node matching the "from"
> expression both counted if they match the "count" expression?
> 
> The algorithm in the XSLT 2.0 draft seems to count both, and xsltproc
> does this.  Xalan and xt seem to not count the from node.  I can't
> work out what saxon is doing.
> 
> For concreteness, here is a stylesheet and a document.  What should
> the output be?
> 
> Stylesheet:
> 
> <xsl:stylesheet version="1.0" 
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
> 
> <xsl:template match="/">
>  <doc>
>   <xsl:text>&#10;</xsl:text>
>   <xsl:apply-templates/>
>   <xsl:text>&#10;</xsl:text>
>  </doc>
> </xsl:template>
> 
> <xsl:template match="*">
>   <xsl:copy>
>     <xsl:attribute name="count">
>       <xsl:number level="any" count="x" from="/*"/>
>     </xsl:attribute>
>     <xsl:apply-templates select="node()"/>
>   </xsl:copy>
> </xsl:template>
> 
> </xsl:stylesheet>
> 
> Document:
> 
> <x>
>  <x/>
>  <x/>
> </x>
> 
> -- Richard

Current Thread