This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 9840 - [XSLT 2.0] xsl:number level="single" has different behaviour to XSLT 1.0
Summary: [XSLT 2.0] xsl:number level="single" has different behaviour to XSLT 1.0
Status: CLOSED WORKSFORME
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XSLT 2.0 (show other bugs)
Version: Recommendation
Hardware: PC Windows NT
: P2 normal
Target Milestone: ---
Assignee: Michael Kay
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-06-03 10:52 UTC by Nick Jones
Modified: 2010-07-27 21:02 UTC (History)
3 users (show)

See Also:


Attachments

Description Nick Jones 2010-06-03 10:52:17 UTC
I believe the numbering behaviour described in XSLT 2.0 is different to that in XSLT 1. It's unclear if this is intentional - it is show up by numbering63 in the test suite.

Consider:

<doc>
  <a>
    <title/>
  </a>
</doc>

On the title node evaluate:

<xsl:number from="a" count="a" level="single"/>

From the XSLT 2 spec:

$S := <title/>

$A := $S/ancestor-or-self::node()[matches-count(.)][1]
   := <a>

$F := $S/ancestor-or-self::node()[matches-from(.)][1]
   := <a>

$AF := $A[ancestor-or-self::node()[. is $F]]
    := <a>

If $AF is empty, return the empty sequence, ()
Otherwise return the value of:
1 + count($AF/preceding-sibling::node()[matches-count(.)])

There for the result is 1


From XSLT 1:

When level="single", it goes up to the first node in the ancestor-or-self axis that matches the count pattern, and constructs a list of length one containing one plus the number of preceding siblings of that ancestor that match the count  pattern. If there is no such ancestor, it constructs an empty list. If the from attribute is specified, then the only ancestors that are searched are those that are descendants of the nearest ancestor that matches the from pattern. Preceding siblings has the same meaning here as with the preceding-sibling axis.

I believe the sentence "If the from attribute is specified, then the only ancestors that are searched are those that are descendants of the nearest ancestor that matches the from pattern." is describing the equivalent of:

$AF := $A[ancestor::node()[. is $F]]
    := ()

Hence resulting in the output being empty-sequence
Comment 1 Michael Kay 2010-06-03 13:26:07 UTC
After this length of time, it's difficult to remember all the details of the reasoning that went into this. I know we spent a lot of time trying to understand exactly what the XSLT 1.0 spec was trying to say, and filling the gaps when it seemed incomplete or inconsistent.

The first problem with the 1.0 text is that it says nothing about what happens when there is no ancestor node that matches the from pattern - which doesn't affect this case, but affected a lot of the thinking about how to rewrite the rule. The second problem is that some uses of "ancestor" in this sentence - notably the first one "that ancestor" - only make sense if read as ancestor-or-self; and presumably we decided this was also the intended reading in the phrase "descendants of the nearest ancestor that matches the from pattern".

Generally we took the view that xsl:number was sufficiently under-specified in corner cases that we could afford to be a little cavalier about compatibility. In some cases (see bug #5849 for one example that arose after the Rec was published - there were other cases during spec development) we took the trouble to investigate behaviour of existing implementations, and found that it was highly variable.
Comment 2 Nick Jones 2010-06-03 13:39:00 UTC
OK. In that case, assuming the XSLT 2.0 definition is correct I'll close this and open a bug against the test suite.
Comment 3 Michael Kay 2010-06-03 14:11:19 UTC
I'm re-opening this because I think it needs WG consideration.

As you point out in test bug 833, there is a test case whose result disagrees with the spec (and therefore, probably several products that disagree with the spec) so we need to consider whether to change the spec or change the test.
Comment 4 Michael Kay 2010-06-03 16:28:32 UTC
The WG looked at this and asked for feedback on the behaviour of current implementations (that is, the results they deliver for test numbering63).

(Saxon returns the "expected" results, i.e. the results that appear to be inconsistent with the spec)
Comment 5 Henry Zongaro 2010-06-03 20:30:27 UTC
IBM's XSLT 2.0 processor returns the result expected by the numbering63 test case.
Comment 6 Nick Jones 2010-06-04 09:27:13 UTC
XQSharp XSLT 2.0 support is currently being developed and currently matches the specification rather than the expected result. (Although hasn't been released yet so changing the behaviour to match a modified specification should be fairly inconsequential).
Comment 7 Russell Davoli 2010-06-04 19:46:57 UTC
Intel's XSLT 2.0 processor produces a result that I believe matches the specification.  For reference, here is the result:

<?xml version="1.0" encoding="UTF-8"?>
<out>: Test for source tree numbering
1: Level A
1: Level B
2: Level B
1: Level C
3: Level B
1: Level C
1: Level D
2: Level A
1: Level B
1: Level C
1: Level D
1: Level E
3: Level A
1: Level B
1: Level C
1: Level D
1: Level E
2: Level D
1: Level E
2: Level C
1: Level D
2: Level B
</out>
Comment 8 Michael Kay 2010-07-01 15:53:53 UTC
We've done some surveys of products, both 1.0 and 2.0 processors. Let's call the two behaviors the "ancestor" or A behaviour (producing an empty result for this case), and the "ancestor-or-self" or AOS behaviour (producing the value 1).

1.0 processors

Saxon 6.5 A
Intel AOS
Xalan-J AOS
XSLTC AOS
IBM JDK 6 A
libxslt A
MSXML3-6 A
.NET XslTransform, XslCompiledTransform A
tDOM AOS


2.0 processors

Saxon 9.2 A
Intel AOS
IBM A
XSharp AOS

I'm inclined to suggest from this data that there is not a strong case for changing the 2.0 spec (to use A rather than AOS); I suggest we should confirm the existing spec and change the test case to match.
Comment 9 Michael Kay 2010-07-15 09:51:19 UTC
Decided on 1 July 2010 to use the ancestor-or-self behaviour, as proposed in comment #8. So no change to the spec, only to change the test case.