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 30105 - [xslt30ts] X/copy-of() and X/snapshot() - order of results
Summary: [xslt30ts] X/copy-of() and X/snapshot() - order of results
Status: NEW
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XSLT 3.0 Test Suite (show other bugs)
Version: Proposed Recommendation
Hardware: PC All
: P2 normal
Target Milestone: ---
Assignee: Abel Braaksma
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-04-29 19:46 UTC by Michael Kay
Modified: 2019-02-26 01:28 UTC (History)
1 user (show)

See Also:


Attachments

Description Michael Kay 2017-04-29 19:46:30 UTC
We have some 15 tests that use a path expression ending in /snapshot(), and some 69 tests that use a path expression ending in /copy-of(), and in nearly all these cases we assume that the result of X/snapshot() or X/copy-of() will correspond with the order of X nodes. However, as we point out in a note in 19.7 of the spec, there is no guarantee of this: the order of nodes in the result of an expression such as X/snapshot() is completely unpredictable.

Example: test square-array-019

(I am currently puzzling about why Saxon-HE is returning these results in a different order from Saxon-EE. That's an internal problem, but it exposed the fact that the tests are making unwarranted assumptions.)
Comment 1 Michael Kay 2017-04-29 19:47:59 UTC
Note, I think it should be possible in most cases to fix the test by using the "!" operator in place of "/".
Comment 2 Michael Kay 2017-04-29 21:28:29 UTC
(Results of investigation for anyone who is interested:

There's a couple of lines of code in Saxon-EE, originally intended to be for streamed-mode only, which decide that X/snapshot() is deemed to be in document order; because we can choose what the document order of snapshots is, we'll deem it to be the order in which they are created. This code isn't present for Saxon-HE. As a result, Saxon-HE is sorting the result of the expression into document order, and Saxon-EE is not. Trees are sorted in order of document number, and document number for a snapshot is not allocated at snapshot creation time, but at the time a document number is first requested. The first time a document number is requested is when Quicksort asks to compare the document order of two snapshots, and since Quicksort picks nodes to compare effectively at random, the effect is to randomize the order of the sequence. Which is all perfectly conformant, but not especially helpful.

And the bottom line is that the tests are wrong.)
Comment 3 Michael Kay 2017-10-09 16:16:54 UTC
The same problem applies to test copy-4501. This does:

<xsl:function name="f:copy-node">
    <xsl:param name="n" as="node()"/>
    <xsl:copy select="$n">
        <xsl:attribute name="position" select="position()"/>
        <xsl:attribute name="last" select="last()"/>
        <xsl:sequence select="*/f:copy-node(.)"/>
    </xsl:copy>
</xsl:function>

There is no guarantee that the order of nodes in */copy-node(.) will reflect the order of nodes in "*".

I think it's producing an unexpected order in Saxon-JS because we sort on allocated document numbers, and we allocate document numbers sequentially, but we sort them as strings not as numbers!
Comment 4 Abel Braaksma 2017-10-09 17:43:40 UTC
> There is no guarantee that the order of nodes in */copy-node(.) will reflect the order of nodes in "*".
It is a strange, subtle and rather inconvenience coincidence of the rules for document nodes that such an expression can cause a different ordering. I find it hard to explain, even to myself ;).

But we can't do anything about that. But perhaps we should rewrite the expressions here to have a more best-practice scenario. Either by f:copy-of(*) (and the equivalent for fn:copy-of) or by using * ! copy-of(.), which I think should keep the order.
Comment 5 Abel Braaksma 2019-02-26 01:28:45 UTC
Not certain whether there's still an action open, otherwise I propose to close this as resolved.