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 29697 - [XSLT30]With nested xsl:merge, should the current-merge-group() of outer merge be available for a merge group selection of inner merge?
Summary: [XSLT30]With nested xsl:merge, should the current-merge-group() of outer merg...
Status: CLOSED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XSLT 3.0 (show other bugs)
Version: Candidate 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: 2016-06-18 09:25 UTC by Martin Honnen
Modified: 2016-10-06 18:42 UTC (History)
0 users

See Also:


Attachments
sample input data for test case (453 bytes, text/xml)
2016-06-18 09:25 UTC, Martin Honnen
Details
reduced test case (971 bytes, application/xml)
2016-06-18 09:26 UTC, Martin Honnen
Details

Description Martin Honnen 2016-06-18 09:25:14 UTC
Created attachment 1645 [details]
sample input data for test case

The following code has two nested xsl:merge, where an xsl:merge-source/@select of the inner xsl:merge tries to select the current-merge-group() of the outer xsl:merge:

	<xsl:template match="root">
		<xsl:copy>
			<xsl:merge>
				<xsl:merge-source select="item">
					<xsl:merge-key select="foo"/>
				</xsl:merge-source>
				<xsl:merge-action>
					<group key="{current-merge-key()}">
						<xsl:merge>
							<xsl:merge-source select="current-merge-group()">
								<xsl:merge-key select="bar"></xsl:merge-key>
							</xsl:merge-source>
							<xsl:merge-action>
								<nested-group key="{current-merge-key()}">
									<xsl:copy-of select="current-merge-group()/value"/>
								</nested-group>
							</xsl:merge-action>
						</xsl:merge>
					</group>
				</xsl:merge-action>
			</xsl:merge>
		</xsl:copy>
	</xsl:template>

This works fine with Exselt, however Saxon (tested with 9.7.0.5 EE) complains

Error in xsl:merge-source/@select on line 18 column 57 of test2016061801.xsl:
  XTDE3480: There is no current merge group

So with Saxon I have to use a variable, as in 

			<xsl:merge>
				<xsl:merge-source select="item">
					<xsl:merge-key select="foo"/>
				</xsl:merge-source>
				<xsl:merge-action>
					<group key="{current-merge-key()}">
						<xsl:variable name="group" select="current-merge-group()"/>
						<xsl:merge>
							<xsl:merge-source select="$group">
								<xsl:merge-key select="bar"></xsl:merge-key>
							</xsl:merge-source>
							<xsl:merge-action>
								<nested-group key="{current-merge-key()}">
									<xsl:copy-of select="current-merge-group()/value"/>
								</nested-group>
							</xsl:merge-action>
						</xsl:merge>
					</group>
				</xsl:merge-action>
			</xsl:merge>


So I would like a clarification whether with nested xsl:merge the current-merge-group() of an outer xsl:merge should be accessible with an xsl:merge-source of a inner xsl:merge.
Comment 1 Martin Honnen 2016-06-18 09:26:22 UTC
Created attachment 1646 [details]
reduced test case
Comment 2 Michael Kay 2016-06-19 07:57:33 UTC
Thanks for raising this.

I think that

(a) the spec doesn't currently provide a clear answer to the question

(b) it's desirable that this test case should work, i.e that the parent merge key/merge group should be available except within the merge-action of the child

(c) in looking for analogies in xsl:for-each-group, I'm not sure the text is very clear there either.
Comment 3 Michael Kay 2016-06-23 17:24:15 UTC
Abel referred us to this text which provides an indication of the intent:

If neither of for-each-item and for-each-stream is present, the xsl:merge-source element defines a single merge input sequence. This sequence is the result of evaluating the expression in the select attribute. *This is evaluated using the dynamic context of the containing xsl:merge instruction.* This sequence will be merged with the sequences defined by other xsl:merge-source elements, if present.

The editor was actioned to come up with a proposal for clarification of the rules.
Comment 4 Michael Kay 2016-06-26 19:46:52 UTC
There seem to be a number of cases we have to consider.

(A) xsl:merge-source/@select when there is no @for-each-item or @for-each-stream. In this case we state "[The select expression] is evaluated using the dynamic context of the containing xsl:merge instruction. This is the case that applies to this example, and it makes it pretty clear that the example should work.

(B) xsl:merge-source/@for-each-item. Here we say:

(B1) The for-each-item expression is evaluated with the dynamic context of the containing xsl:merge instruction

(B2) the select attribute is evaluated with the focus for the evaluation as follows...

We don't explicitly say anything about other aspects of the dynamic context for the evaluation of the select attribute.

(C) xsl:merge-source/@for-each-stream. 

(C1) We don't say anything about the dynamic context for the evaluation of for-each-stream.

(C2) We say "These anchor items are then used in the same way as a sequence of anchor items selected directly using the for-each-item attribute." which hints that the dynamic context for the select expression follows the same rules as in the for-each-item case.

(D) xsl:merge-key/@select (or the contained sequence constructor): we say "This is evaluated with a singleton focus based on J, or, if streamable=yes is specified on the xsl:merge-source, a singleton focus based on a snapshot of J (see 15.4 Streamable Merging)." We say nothing about other aspects of the dynamic context.

(E) Attribute value templates on xsl:merge-key: we say "their effective values are evaluated using the focus of the containing xsl:merge instruction." We say nothing about other aspects of the dynamic context.

In 15.6 we have a non-normative note: "The current merge group and key are set during the evaluation of the sequence constructor contained in the xsl:merge-action element. They are initially absent, and they are cleared by all invocation constructs, which means in effect that the functions current-merge-group and current-merge-key can only usefully be invoked from instructions appearing lexically within the xsl:merge-action element." But this doesn't help us much because all these cases are lexically within the xsl:merge-action of the outer xsl:merge.

The statement that the current merge group and key are cleared by all invocation constructs appears normatively in 15.6.1 and 15.6.2.

Section 5.3, the general description of the static and dynamic context, sheds no additional light: for these components it delegates entirely to 15.6.

I think we should add the general rules (in 15.6): (part of this is transferred from 15.6.1 and 15.6.2).

<quote>
The current merge group and current merge key are available within the sequence constructor contained by an xsl:merge-action element. The values are initially absent during the evaluation of global variables and stylesheet parameters, during the evaluation of the use attribute or contained sequence constructor of xsl:key, and during the evaluation of the initial-value attribute of xsl:accumulator and the select attribute of contained sequence constructor of xsl:accumulator-rule. All invocation constructs set the current merge group and current merge key to absent. 

Note: Taken together, these rules mean that any invocation of current-merge-group or current-merge-key that is not lexically scoped by an xsl:merge-action element will raise a dynamic error.

When an inner xsl:merge instruction is lexically nested within the xsl:merge-action element of an outer xsl:merge instruction, any use of current-merge-group or current-merge-key that appears within the xsl:merge-action of the inner xsl:merge instruction is a reference to the current merge group or key of the inner xsl:merge instruction, while any such reference that appears within the outer xsl:merge-action element, but not within the inner xsl:merge-action, is a reference to the current merge group or key of the outer xsl:merge instruction. This means, for example, that a reference to the current merge group of the outer xsl:merge can appear in the select attribute of an xsl:merge-source child of the inner xsl:merge.
</quote>

Additional changes: 

In 15.3, after "When the for-each-stream attribute is present, its value must be an expression that returns a sequence of URIs." add "The expression is evaluated with the dynamic context of the containing xsl:merge instruction." After "These anchor items are then used in the same way as a sequence of anchor items selected directly using the for-each-item attribute." add: "in particular, the focus for the select expression is established in the same way.
Comment 5 Michael Kay 2016-06-26 21:31:37 UTC
Test case added - merge-089

I have updated the spec as proposed in comment #4.
Comment 6 Michael Kay 2016-07-07 17:20:08 UTC
The change was accepted.