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 29141 - [XSLT30] fn:snapshot and fn:copy-of talk about node (singular), where the signature allows nodes
Summary: [XSLT30] fn:snapshot and fn:copy-of talk about node (singular), where the sig...
Status: CLOSED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XSLT 3.0 (show other bugs)
Version: Last Call drafts
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: 2015-09-23 12:46 UTC by Abel Braaksma
Modified: 2015-10-29 12:42 UTC (History)
0 users

See Also:


Attachments

Description Abel Braaksma 2015-09-23 12:46:36 UTC
In 18.3, the summary text of fn:copy-of says:

    "Returns a deep copy of the node supplied as the $node argument, or of 
    the context node if the argument is absent."

I think this should be "deep copy of the nodes" and "as the $nodes argument".

In 18.4, the summary text of fn:snapshot says:

    "Returns a copy of a node together with its ancestors and descendants and 
    their attributes and namespaces."

I think this should be "Returns a copy of a sequence of nodes".

The body of the text has:

    "The function returns a sequence of nodes in which each node is a 
    snapshot of the corresponding node in the input sequence supplied as the 
    argument $node. If the argument is an empty sequence, the function 
    returns an empty sequence."

This should be "supplied as the argument $nodes", according to the signature.

The function used to explain its workings has a return type of "node()?", this should be "node()*":

    <xsl:function name="fn:snapshot" as="node()?" new-each-time="maybe">

should then become

    <xsl:function name="fn:snapshot" as="node()*" new-each-time="maybe">

The body of the function already allows a sequence of nodes to be returned.
Comment 1 Michael Kay 2015-09-23 20:58:29 UTC
Yes, the change to make these functions work on sequences of nodes was clearly only implemented partially.

John Lumley also points out that we ought to be clear in the case where the same node is present more than once in the input sequence whether the output sequence will also contain the same node more than once, or whether each gets a different copy, or whether this is implementation-dependent. In keeping with the use of new-each-time="maybe", I think it should be implementation-dependent. 

More complex scenarios are also possible, where the input sequence to copy() or snapshot() contains a node N and also one or more of its ancestor or descendant nodes. We could either allow the result to contain overlapping copies in this case, or we could insist that in the result of copy-of, each node is parentless and siblingless, and in the result of snapshot, each node is siblingless (which would imply multiple copies).
Comment 2 Abel Braaksma 2015-09-24 07:55:22 UTC
(In reply to Michael Kay from comment #1)

> More complex scenarios are also possible, where the input sequence to copy()
> or snapshot() contains a node N and also one or more of its ancestor or
> descendant nodes. We could either allow the result to contain overlapping
> copies in this case, or we could insist that in the result of copy-of, each
> node is parentless and siblingless, and in the result of snapshot, each node
> is siblingless (which would imply multiple copies).

You mean as in:

copy-of(.. | .)

to return only the parent, as it already includes the current node? I think as presently written, it returns a deep copy of the parent and a deep copy of the current node, both being parentless. I think snapshot() should work the same way.

Which is in line with applying templates with on-no-match="deep-copy".


(In reply to Michael Kay from comment #1)
> John Lumley also points out that we ought to be clear in the case where the
> same node is present more than once in the input sequence whether the output
> sequence will also contain the same node more than once, or whether each
> gets a different copy, or whether this is implementation-dependent. In
> keeping with the use of new-each-time="maybe", I think it should be
> implementation-dependent. 

I agree, it should be implementation-dependent.
Comment 3 Abel Braaksma 2015-09-24 08:03:46 UTC
Does it make sense (and isn't it too big a change) to allow any sequence as input to copy-of() and snapshot(), where in the case of atomic values, it is simply a no-op? Apart from the signature, I don't think the rules have to change.

I think it makes things simpler, i.e. it would help with generic scenarios where input can be anything, and users won't have to write the following, which seems silly:

> if($input instance of node()) then copy-of($input) else $input

It also helps with making streaming xsl:merge behave more stable and less surprising in the event the xsl:merge-source/@select selects non-nodes or a mix of nodes and atomic values (see bug 29142)
Comment 4 Michael Kay 2015-09-28 10:18:00 UTC
In response to comment #2, I think the question is, what can we say about the following expressions:

(a) count($X) eq count(copy-of($X))

(b) every $x in copy-of($X) satisfies empty($x/..)

(c) let $R := copy-of(.., .) return $R[1] is $R[2]/..

I think (a) should always be true (for any input $X)

On balance I think (b) should always be true (i.e. all nodes in the result are parentless)

That would mean that (c) is false: although you've already copied "." in the course of copying "..", you have to copy it again when processing the second item in the input sequence, because the first copy wasn't parentless.

In response to comment #3, although one could specify copy-of and snapshot to be no-ops when applied to atomic values or functions, I don't think it's useful enough to justify a spec change at this stage.
Comment 5 Michael Kay 2015-10-08 16:58:19 UTC
In discussion we were inclined to propose:

* copy-of follows the same rules as xsl:copy-of

** therefore it accepts items of any kind

** copy-of($seq) delivers the same result as $seq!copy-of(.), that is, each item is copied independently; if the same node appears twice you get two different copies; all nodes in the result are parentless

** snapshot, similarly, accepts items of any kind
Comment 6 Michael Kay 2015-10-09 19:57:43 UTC
The changes were approved and have been applied.
Comment 7 Michael Kay 2015-10-22 19:32:40 UTC
Some minor improvements to the stylesheet were suggested in email and have been incorporated.