Bug #2928
closedIncorrect xsl:number interpretation
0%
Description
Saxon-9HE 9.7.0.8J (and earlier versions) incorrectly begin xsl:number level="multiple" at the node matched rather than the ancestral child of the node matched by from="". Saxon 6.5.5 produces the correct result.
I've marked this "high" because it is a conformance issue and it happens to be impacting on my development this month. It has taken me a while to whittle down the evidence to the attached simple example. Below is the transcript running both Saxon-9HE and Saxon.
Thank you for looking at this issue.
. . . . . . . Ken
~/t/ftemp $ java -jar ~/p/xml/xslt/saxon9he/saxon9he.jar
No source file name
Saxon-HE 9.7.0.8J from Saxonica
Usage: see http://www.saxonica.com/html/documentation/using-xsl/commandline.html
Format: net.sf.saxon.Transform options params
Options available: -? -a -catalog -config -cr -diag -dtd -ea -expand -explain -export -ext -im -init -it -l -license -m -nogo -now -o -opt -or -outval -p -pack -quit -r -repeat -s -sa -scmin -strip -t -T -target -threads -TJ -TP -traceout -tree -u -val -versionmsg -warnings -x -xi -xmlversion -xsd -xsdversion -xsiloc -xsl -xsltversion -y
Use -XYZ:? for details of option XYZ
Params:
param=value Set stylesheet string parameter
+param=filename Set stylesheet document parameter
?param=expression Set stylesheet parameter using XPath
!param=value Set serialization parameter
~/t/ftemp $ java -jar ~/p/xml/xslt/saxon9he/saxon9he.jar -xsl:testNumber.xsl -s:testNumber.xml
From the top
1.1.1 First test
1.1.2 Second test
1.1.3 Third test
From one level down
1.1 First test
1.2 Second test
1.3 Third test
~/t/ftemp $ java -jar ~/p/xml/xslt/saxon/saxon.jar
No source file name
SAXON 6.5.5 from Michael Kay
Usage: java com.icl.saxon.StyleSheet [options] source-doc style-doc {param=value}...
Options:
-a Use xml-stylesheet PI, not style-doc argument
-ds Use standard tree data structure
-dt Use tinytree data structure (default)
-o filename Send output to named file or directory
-m classname Use specified Emitter class for xsl:message output
-r classname Use specified URIResolver class
-t Display version and timing information
-T Set standard TraceListener
-TL classname Set a specific TraceListener
-u Names are URLs not filenames
-w0 Recover silently from recoverable errors
-w1 Report recoverable errors and continue (default)
-w2 Treat recoverable errors as fatal
-x classname Use specified SAX parser for source file
-y classname Use specified SAX parser for stylesheet
-? Display this message
~/t/ftemp $ java -jar ~/p/xml/xslt/saxon/saxon.jar testNumber.xml testNumber.xsl
From the top
1.1 First test
1.2 Second test
1.3 Third test
From one level down
1 First test
2 Second test
3 Third test
~/t/ftemp $ cat testNumber.xml
<section role='terms'>
<here>
<section>First test</section>
<section>Second test</section>
<section>Third test</section>
</here>
</section>
~/t/ftemp $ cat testNumber.xsl
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="text"/>
<xsl:template match="/">
xsl:textFrom the top </xsl:text>
<xsl:for-each select="//here/section">
<xsl:number count="section" from="section[parent::test]"
level="multiple"/>
<xsl:text> </xsl:text>
<xsl:value-of select="."/>
<xsl:text>
</xsl:text>
</xsl:for-each>
xsl:textFrom one level down </xsl:text>
<xsl:for-each select="//here/section">
<xsl:number count="section" from="section[@role='terms']"
level="multiple"/>
<xsl:text> </xsl:text>
<xsl:value-of select="."/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>~/t/ftemp $
Files
Updated by Michael Kay about 8 years ago
I think the behaviour is correct.
I think there was a spec change here. XSLT 1.0 says:
When level="multiple", it constructs a list of all ancestors of the current node in document order followed by the element itself; it then selects from the list those nodes that match the count pattern; it then maps each node in the list to one plus the number of preceding siblings of that node that match the count pattern. 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.
While XSLT 2.0 says
Let $A be the node sequence selected by the expression
$S/ancestor-or-self::node()[matches-count(.)]
(the set of ancestor-or-self nodes that match the count pattern)
Let $F be the node sequence selected by the expression
$S/ancestor-or-self::node()[matches-from(.)][1]
(the innermost ancestor-or-self node that matches the from pattern)
Let $AF be the value of
$A[ancestor-or-self::node()[. is $F]]
(the nodes selected in the first step that are in the subtree rooted at the node selected in the second step)
Return the result of the expression
for $af in $AF return 1+count($af/preceding-sibling::node()[matches-count(.)])
(a sequence of integers containing, for each of these nodes, one plus the number of preceding siblings that match the count pattern)
If the nearest ancestor node that matches the from pattern also matches the count pattern, then the 1.0 rules don't count it, but the 2.0/3.0 rules do.
I don't remember how this happened - it's all a long time ago! I do seem to recall that we designed the 2.0 rules to fix some glaring ambiguities in the 1.0 spec, and after doing so found we had inadvertently changed the behavior for some cases that were not really ambiguous at all. The WG actually went as far as examining the behaviour of 1.0 products in some areas, and generally discovered that in areas where there was a potential incompatibility, the behaviour of 1.0 processors was all over the place already.
See in particular https://www.w3.org/Bugs/Public/show_bug.cgi?id=9840 which although it's not about level="multiple", did lead to some agonising over whether the 1.0 spec always said what it intended to say.
Updated by Ken Holman about 8 years ago
Ouch! Thank you for letting me know. Forgive me for taking up the bandwidth. I suppose the ticket can be closed with no action.
Updated by Michael Kay about 8 years ago
- Status changed from New to Closed
- Assignee set to Michael Kay
- Priority changed from High to Normal
No problem, it's knowing that we have users who are affected by such details that keeps us going!
Please register to edit this issue