Project

Profile

Help

xsl:merge-source for-each-source, streamable="yes" and Saxon HE

Added by Martin Honnen over 5 years ago

I think my attempt to file bug https://saxonica.plan.io/issues/3883 on Saxon 9.8 resulted in the test case https://dvcs.w3.org/hg/xslt30-test/file/tip/tests/insn/merge/merge-097.xsl.

https://saxonica.plan.io/issues/3883#note-10 says "This has been fixed on the 9.9 branch" but either I still misunderstand what the spec says or the issue still exists in Saxon 9.9.

The spec https://www.w3.org/TR/xslt-30/#streamable-merging says

When streamable="yes" is specified on an xsl:merge-source element, then (whether or not streamed processing is actually used, and whether or not the processor supports streaming) the expression appearing in the select attribute is implicitly used as the argument of a call on the snapshot function

Based on that I would both Saxon 9.9 EE and Saxon 9.9 HE expect to work with a snapshot in a construct like

            <xsl:merge>
                <xsl:merge-source for-each-source="'input1.xml'" select="*/*/*" streamable="yes">
                    <xsl:merge-key select="true()"/>
                </xsl:merge-source>
                <xsl:merge-action>
                    <merge-group position="{position()}">
                        <xsl:apply-templates select="current-merge-group()"/>
                    </merge-group>
                </xsl:merge-action>
            </xsl:merge>

and to deliver the same results, but I get different results with EE and HE, as I do get for the cited W3C test case (as long as the default value for <xsl:param name="STREAMABLE" static="true" select="true()"/> is kept).

So is this behaviour considered correct?

For completeness, the above, in an attempt to construct a minimal test case, is in

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">
    
    <xsl:output indent="yes"/>
    
    <xsl:mode on-no-match="shallow-copy"/>
    
    <xsl:template name="xsl:initial-template" match="/">
        <result-root>
            <xsl:merge>
                <xsl:merge-source for-each-source="'input1.xml'" select="*/*/*" streamable="yes">
                    <xsl:merge-key select="true()"/>
                </xsl:merge-source>
                <xsl:merge-action>
                    <merge-group position="{position()}">
                        <xsl:apply-templates select="current-merge-group()"/>
                    </merge-group>
                </xsl:merge-action>
            </xsl:merge>
        </result-root>
    </xsl:template>
    
    <xsl:template match="/*/*/*">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:attribute name="position" select="position()"/>
            <xsl:attribute name="sibling-count" select="count((preceding-sibling::*, following-sibling::*))"/>
            <xsl:apply-templates/>
        </xsl:copy>
        <xsl:assert test="count((preceding-sibling::*, following-sibling::*)) = 0">Snapshot created by merge has siblings</xsl:assert>
    </xsl:template>
    
</xsl:stylesheet>

and an input sample is as before

<?xml version="1.0" encoding="UTF-8"?>
<root>
	<items>
		<item>
			<foo>foo 1, file 1</foo>
			<name>name 1, file 1</name>
		</item>
		<item>
			<foo>foo 2, file 1</foo>
			<name>name 2, file 1</name>
		</item>
	</items>
</root>

and when I run with Saxon Saxon-EE 9.9.0.1J with options -t -it I get

<result-root>
   <merge-group position="1">
      <item position="1" sibling-count="0">
         <foo>foo 1, file 1</foo>
         <name>name 1, file 1</name>
      </item>
      <item position="2" sibling-count="0">
         <foo>foo 2, file 1</foo>
         <name>name 2, file 1</name>
      </item>
   </merge-group>
</result-root>

while Saxon-HE 9.9.0.1J gives

<result-root>
   <merge-group position="1">
      <item position="1" sibling-count="1">
         <foo>foo 1, file 1</foo>
         <name>name 1, file 1</name>
      </item>
      <item position="2" sibling-count="1">
         <foo>foo 2, file 1</foo>
         <name>name 2, file 1</name>
      </item>
   </merge-group>
</result-root>

and when I add the option -ea to enable assertions HE abandons processing with

Snapshot created by merge has siblings Error evaluating ((attr{position=...}, ...)) on line 33 column 84 of test-merge-snapshot5.xsl: XTMM9001: Processing terminated by xsl:assert at line 33 in test-merge-snapshot5.xsl

while EE doesn't raise the assertion.


Please register to reply