Bug #6472
openSort order not recognised for xsl:for-each-group in named template (Saxon HE 12.xJ)
0%
Description
I have an issue setting the sort order for xsl:for-each-group via a xsl:param inside a named template. When I call the same template more than once it seems to remember the sort order from the first call.
The first call to the template sets the param to 'descending' and the output is in the expected order.
The second call to the template sets the param to 'ascending' and the output is in descending order.
This happens in 12.x (I tried 12.0, 12.4 and 12.5) but is fine in 11.6.
My stylesheet is:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="data">
<root>
<item name="bbb" />
<item name="ddd" />
<item name="bbb" />
<item name="aaa" />
<item name="ccc" />
</root>
</xsl:variable>
<xsl:template name="xsl:initial-template">
<root>
<xsl:call-template name="fegTemplate">
<xsl:with-param name="ordering">descending</xsl:with-param>
</xsl:call-template>
<xsl:call-template name="fegTemplate">
<xsl:with-param name="ordering">ascending</xsl:with-param>
</xsl:call-template>
</root>
</xsl:template>
<xsl:template name="fegTemplate">
<xsl:param name="ordering" select="string('ascending')" />
<h>for-each-group <xsl:value-of select="$ordering" /></h>
<xsl:for-each-group select="$data/root/item" group-by="@name">
<xsl:sort order="{$ordering}" select="current-grouping-key()" />
<t><xsl:value-of select="current-grouping-key()" /></t>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
The first call sets the 'ordering' param to 'descending' and the second call sets it to 'ascending'. With 12.xJ the output from the second call is in descending order:
<root>
<h>for-each-group descending</h>
<t>ddd</t>
<t>ccc</t>
<t>bbb</t>
<t>aaa</t>
<h>for-each-group ascending</h>
<t>ddd</t>
<t>ccc</t>
<t>bbb</t>
<t>aaa</t>
</root>
With 11.6 the output is as expected:
<root>
<h>for-each-group descending</h>
<t>ddd</t>
<t>ccc</t>
<t>bbb</t>
<t>aaa</t>
<h>for-each-group ascending</h>
<t>aaa</t>
<t>bbb</t>
<t>ccc</t>
<t>ddd</t>
</root>
Adrian
Files
Updated by Martin Honnen 9 days ago
Weird bug.
I tried to check whether using a function instead of a template helps but the code
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet
version="3.0"
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"
expand-text="yes">
<xsl:variable name="data">
<root>
<item name="bbb" />
<item name="ddd" />
<item name="bbb" />
<item name="aaa" />
<item name="ccc" />
</root>
</xsl:variable>
<xsl:function name="mf:group-and-sort" as="element(t)*">
<xsl:param name="items" as="element(item)*"/>
<xsl:param name="ordering" as="xs:string"/>
<xsl:for-each-group select="$items" group-by="@name">
<xsl:sort select="current-grouping-key()" order="{$ordering}"/>
<t>{current-grouping-key()}</t>
</xsl:for-each-group>
</xsl:function>
<xsl:output indent="yes"/>
<xsl:template name="xsl:initial-template">
<root>
<xsl:for-each select="'descending', 'ascending'">
<order>{.}</order>
<xsl:sequence select="mf:group-and-sort($data/root/item, .)"/>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
with 12.5 gives the same wrong result
<?xml version="1.0" encoding="UTF-8"?>
<root>
<order>descending</order>
<t>ddd</t>
<t>ccc</t>
<t>bbb</t>
<t>aaa</t>
<order>ascending</order>
<t>ddd</t>
<t>ccc</t>
<t>bbb</t>
<t>aaa</t>
</root>
Trying with Saxon 12.5 EE for SaxonJS reveals (perhaps?) the root of the problems (Internal Saxon error: local variable encountered whose binding has been deleted
)
*** Internal Saxon error: local variable encountered whose binding has been deleted
Variable name: ordering
Line number of reference: 24 in file:/C:/Users/marti/OneDrive/Documents/xslt/blog-xslt-3-by-example/saxon12-group-order-bug/./sheet2.xsl
Line number of declaration: 35 in file:/C:/Users/marti/OneDrive/Documents/xslt/blog-xslt-3-by-example/saxon12-group-order-bug/./sheet2.xsl
DECLARATION:
<?xml version="1.0" encoding="utf-8"?>
<let baseUri='file:/C:/Users/marti/OneDrive/Documents/xslt/blog-xslt-3-by-example/saxon12-group-order-bug/./sheet2.xsl' ns='mf=http://example.com/mf xs=~ xsl=~' line='35' var='Q{}ordering' as='1AS' slot='-999'>
<dot type='1AS'/>
<forEachGroup line='23' algorithm='by'>
<gVarRef role='select' name='Q{http://saxon.sf.net/generated-variable}gg1419332030' bSlot='-1'/>
<attVal role='key' name='Q{}name'/>
<sortKey role='sort' line='24'>
<check role='select' card='?' diag='4|0|XTTE1020|xsl:sort/select'>
<currentGroupingKey/>
</check>
<fn role='order' name='string-join'>
<varRef name='Q{}ordering' slot='-999'/>
<str val=' '/>
</fn>
<str role='lang' val=''/>
<str role='caseOrder' val='#default'/>
<str role='stable' val='yes'/>
<str role='collation' val='http://www.w3.org/2005/xpath-functions/collation/codepoint'/>
</sortKey>
<str role='collation' val='http://www.w3.org/2005/xpath-functions/collation/codepoint'/>
<elem role='content' line='25' name='t' nsuri='' flags='l'>
<valueOf flags='l'>
<fn name='string-join'>
<convert from='A' to='AS'>
<currentGroupingKey/>
</convert>
<str val=' '/>
</fn>
</valueOf>
</elem>
</forEachGroup>
</let>
java.lang.IllegalStateException: *** Internal Saxon error: local variable encountered whose binding has been deleted
at net.sf.saxon.expr.parser.ExpressionTool.allocateSlots(ExpressionTool.java:636)
at net.sf.saxon.expr.parser.ExpressionTool.allocateSlots(ExpressionTool.java:646)
at net.sf.saxon.expr.parser.ExpressionTool.allocateSlots(ExpressionTool.java:646)
at net.sf.saxon.expr.parser.ExpressionTool.allocateSlots(ExpressionTool.java:646)
at net.sf.saxon.expr.parser.ExpressionTool.allocateSlots(ExpressionTool.java:646)
at net.sf.saxon.expr.parser.ExpressionTool.allocateSlots(ExpressionTool.java:646)
at net.sf.saxon.expr.parser.ExpressionTool.allocateSlots(ExpressionTool.java:646)
at net.sf.saxon.expr.parser.ExpressionTool.allocateSlots(ExpressionTool.java:646)
at net.sf.saxon.style.StyleElement.allocateLocalSlots(StyleElement.java:1606)
at net.sf.saxon.style.XSLTemplate.optimize(XSLTemplate.java:999)
at net.sf.saxon.style.PrincipalStylesheetModule.optimizeTopLevel(PrincipalStylesheetModule.java:1502)
at net.sf.saxon.style.PrincipalStylesheetModule.compile(PrincipalStylesheetModule.java:1321)
at net.sf.saxon.style.Compilation.compilePackage(Compilation.java:341)
at net.sf.saxon.s9api.XsltCompiler.compilePackage(XsltCompiler.java:672)
at net.sf.saxon.Transform.doTransform(Transform.java:777)
at net.sf.saxon.Transform.main(Transform.java:84)
Fatal error during transformation: java.lang.IllegalStateException: *** Internal Saxon error: local variable encountered whose binding has been deleted
Updated by Martin Honnen 9 days ago
"Trying with Saxon 12.5 EE for SaxonJS reveals (perhaps?) the root of the problems" was meant to say "Trying with Saxon 12.5 EE to compile/export for SaxonJS reveals (perhaps?) the root of the problems".
Updated by Michael Kay 7 days ago
Thanks for reporting it.
I can see where it's going wrong: in ForEachGroup
it is doing
expr.makeSortKeyEvaluators();
during the first-time-through code without checking that the sort options are constants.
Updated by Adrian Bird 7 days ago
Is there a way I can rewrite it to get it to work? I have some data I want to output multiple times with different sort keys and ordering, without having to duplicate the output code multiple times (the issue isn't affected by the sort key as a parameter which is why I didn't include it in the test case).
Adrian
Please register to edit this issue