Bug #3884
closedSaxon doesn't allow use of current-merge-group() call in user-defined function call inside of xsl:merge-action, gives error "XTDE3480: There is no current merge group"
100%
Description
Based on Michael Kay's response in https://xsl.markmail.org/message/xlgjiyzoa7emwtjj I file this bug that Saxon doesn't allow the use of current-merge-group()
inside of a user-defined function call argument in an xsl:merge-action
, e.g.
<xsl:merge-action>
<xsl:sequence select="mf:construct-doc(tail(current-merge-group()), .)"/>
</xsl:merge-action>
gives an error "XTDE3480: There is no current merge group".
A reduced, self-contained test case is
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="#all"
version="3.0">
<xsl:param name="select-expression" static="yes" as="xs:string" select="'root/data/foo'"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output indent="yes"/>
<xsl:param name="doc1">
<root>
<data>
<foo>
<value>foo 1, 1</value>
</foo>
<bar>
<value>bar 1, 1</value>
</bar>
<foo>
<value>foo 2, 1</value>
</foo>
</data>
</root>
</xsl:param>
<xsl:param name="doc2">
<root>
<data>
<foo>
<value>foo 1, 2</value>
</foo>
<bar>
<value>bar 1, 2</value>
</bar>
<foo>
<value>foo 2, 2</value>
</foo>
<bar>
<value>bar 2, 2</value>
</bar>
<foo>
<value>foo 3, 2</value>
</foo>
</data>
</root>
</xsl:param>
<xsl:template match="/" name="xsl:initial-template">
<xsl:merge>
<xsl:merge-source for-each-item="$doc1, $doc2" _select="{$select-expression}">
<xsl:merge-key select="true()"/>
</xsl:merge-source>
<xsl:merge-action>
<xsl:sequence select="mf:construct-doc(tail(current-merge-group()), .)"/>
</xsl:merge-action>
</xsl:merge>
</xsl:template>
<xsl:function name="mf:construct-doc" as="document-node()">
<xsl:param name="nodes" as="node()*"/>
<xsl:param name="first-node" as="node()"/>
<xsl:apply-templates select="root($first-node)" mode="construct">
<xsl:with-param name="nodes" select="$nodes"/>
</xsl:apply-templates>
</xsl:function>
<xsl:mode name="construct" on-no-match="shallow-copy"/>
<xsl:template _match="{$select-expression}" mode="construct">
<xsl:param name="nodes"/>
<xsl:apply-templates select="."/>
<xsl:apply-templates select="$nodes"/>
</xsl:template>
</xsl:stylesheet>
when I run it with Saxon 9.8.0.14 HE Java from the command line (-it
) I get an error
Error at char 22 in xsl:sequence/@select on line 58 column 90 of use-current-merge-group-call-as-function-argument1.xsl:
XTDE3480: There is no current merge group There is no current merge group
rewriting the
<xsl:merge-action>
<xsl:sequence select="mf:construct-doc(tail(current-merge-group()), .)"/>
</xsl:merge-action>
to
<xsl:merge-action>
<xsl:sequence select="let $group-tail := tail(current-merge-group()) return mf:construct-doc($group-tail, .)"/>
</xsl:merge-action>
however allows me to run the code, although it exhibits the same duplication of result nodes filed in https://saxonica.plan.io/issues/3883 as a separate bug.
Updated by Michael Kay about 6 years ago
- Status changed from New to In Progress
Problem reproduced; new XSLT 3.0 test case merge-096.
Saxon is deciding to evaluate the argument lazily, which means it creates a MemoClosure that must contain all the information needed to satisfy its dependencies; but the current merge group is not being saved in the MemoClosure so an error occurs when it is finally evaluated.
Note that other context dependencies (such as position() and last()) cause Saxon to evaluate the argument eagerly rather than trying to save the necessary information.
Updated by Michael Kay about 6 years ago
I have been examining how this works if an expression that depends on position() or last() is passed as an argument to a user function call, and I'm coming to the conclusion that there is a problem in that area too. If the expression is very simple (eg. a call on position() itself) then it's evaluated eagerly, but a more complex expression like (1 to position())!(.*.)
is apparently evaluated lazily and as far as I can see the result is going to be wrong.
I have confirmed this bug exists with a new test position-0103.
Updated by Michael Kay about 6 years ago
- Status changed from In Progress to Resolved
- Assignee set to Michael Kay
- Applies to branch trunk added
- Fix Committed on Branch 9.8, trunk added
Updated by Michael Kay about 6 years ago
Fixed both bugs by changing the rules in userFunctionCall.computeEvaluationModes() so that eager evaluation is used if the argument expression has relevant dependencies.
Updated by O'Neil Delpratt about 6 years ago
- % Done changed from 0 to 100
- Fixed in Maintenance Release 9.9.0.1 added
Bug fix applied in the Saxon 9.9.0.1 major release.
Leave open until fix applied in the next Saxon 9.8 maintenance release.
Updated by O'Neil Delpratt about 6 years ago
- Status changed from Resolved to Closed
- Fixed in Maintenance Release 9.8.0.15 added
Bug fix applied in the Saxon 9.8.0.15 maintenance release.
Please register to edit this issue