Project

Profile

Help

Bug #5118

Incorrect handling of multiple xsl:mode declarations for the same mode

Added by Martin Honnen 10 days ago. Updated about 3 hours ago.

Status:
In Progress
Priority:
Normal
Assignee:
-
Category:
XSLT conformance
Sprint/Milestone:
-
Start date:
2021-10-08
Due date:
% Done:

0%

Estimated time:
Legacy ID:
Applies to branch:
10, 11
Fix Committed on Branch:
Fixed in Maintenance Release:
Platforms:

Description

When I try to run a streamable transformation where I have the streamable declaration first in a single <xsl:mode streamable="yes"/> and later on a second xsl:mode with e.g. <xsl:mode on-no-match="shallow-copy"/> both Saxon EE 10.6 Java and SaxonCS 11 EE seem to build a tree based on the TIMING or -t output.

Simple repro: XML:

<root>
  <data>This is a test.</data>
</root>

XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all"
  expand-text="yes">

  <xsl:mode streamable="yes"/>

  <xsl:template match="/" name="xsl:initial-template">
    <xsl:next-match/>
    <xsl:comment>Run with {system-property('xsl:product-name')} {system-property('xsl:product-version')} {system-property('Q{http://saxon.sf.net/}platform')}</xsl:comment>
  </xsl:template>

 <xsl:mode on-no-match="shallow-copy"/>

</xsl:stylesheet>

Output with Saxon EE 10.6 from the command line:

PS C:\Users\marti\OneDrive\Documents\xslt\xslt4-examples\streamable-identity> java -jar 'C:\Program Files\Saxonica\SaxonEE10-6J\saxon-ee-10.6.jar' -t -s:.\input-sample1.xml -xsl:.\identity-streamable-two-separate-mode-declarations1.xsl
Saxon-EE 10.6J from Saxonica
Java version 1.8.0_292
Using license serial number V.....
Stylesheet compilation time: 615.5411ms
Processing file:/C:/Users/marti/OneDrive/Documents/xslt/xslt4-examples/streamable-identity/./input-sample1.xml
Using parser com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser
Building tree for file:/C:/Users/marti/OneDrive/Documents/xslt/xslt4-examples/streamable-identity/./input-sample1.xml using class net.sf.saxon.tree.tiny.TinyBuilder
Tree built in 3.1059ms
Tree size: 6 nodes, 15 characters, 0 attributes
<?xml version="1.0" encoding="UTF-8"?><root>
  <data>This is a test.</data>
</root><!--Run with SAXON EE 10.6 -->Execution time: 88.7911ms
Memory used: 62Mb

Output with SaxonCS:

PS C:\Users\marti\OneDrive\Documents\xslt\xslt4-examples\streamable-identity> & 'C:\Program Files\Saxonica\SaxonCS-11.0\SaxonCS.exe' transform -t -s:.\input-sample1.xml -xsl:.\identity-streamable-two-separate-mode-declarations1.xsl
SaxonCS-EE 11.0 from Saxonica
.NET 5.0.9 on Windows 10.0.19043.0
Using license serial number V.....
Stylesheet compilation time: 566,8583ms
Processing file:///C:/Users/marti/OneDrive/Documents/xslt/xslt4-examples/streamable-identity/input-sample1.xml
Building tree for file:///C:/Users/marti/OneDrive/Documents/xslt/xslt4-examples/streamable-identity/input-sample1.xml using Saxon.Hej.tree.tiny.TinyBuilder
Tree built in 5,9621ms
Tree size: 6 nodes, 65536 characters, 0 attributes
<?xml version="1.0" encoding="UTF-8"?><root>
  <data>This is a test.</data>
</root><!--Run with SAXON EE 11.0 -->Execution time: 100,9325ms
Memory used: 0Mb

History

#1 Updated by Martin Honnen 10 days ago

If the two xsl:mode declarations are reordered to have the one with the explicit streamable="yes" last, as in

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all"
  expand-text="yes">

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="/" name="xsl:initial-template">
    <xsl:next-match/>
    <xsl:comment>Run with {system-property('xsl:product-name')} {system-property('xsl:product-version')} {system-property('Q{http://saxon.sf.net/}platform')}</xsl:comment>
  </xsl:template>

  <xsl:mode streamable="yes"/>

</xsl:stylesheet>

then both Saxon EE 10.6 Java and SaxonCS EE 11 stream.

So the order seems to perhaps in the first, not streamed test case make Saxon use the implicit default of streamable="no" of the second xsl:mode declaration.

But my reading of the spec's text "For the unnamed mode, the effective value of each attribute is taken from an xsl:mode declaration that has no name attribute, and that specifies an explicit value for the required attribute. If there is no such declaration, the default value of the attribute is used. If there is more than one such declaration, the one with highest import precedence is used." is that, as long as there is an xsl:mode with an explicit streamable="yes" and no later, higher import precedence explicit streamable="no", that the explicit streamable="yes" defines the effective value.

#2 Updated by Michael Kay about 16 hours ago

The following query:

-qs:"collection('/Users/mike/GitHub/xslt30-test/tests/attr/mode?select=*.xsl')[count(distinct-values(//*:mode/string(@name))) lt count(//*:mode)]/base-uri(.)"

demonstrates that there is only one test (mode-1502) that has more than one mode with the same name; and that is testing the error case where there are conflicting values for the same attribute.

So the whole area is grossly under-tested.

The Saxon implementation in XSLMode (a) succeeds in creating a single Mode object corresponding to the multiple xsl:mode elements, and (b) (in the validate() method) creates a data structure representing the properties of these modes, identifying conflicts and identifying the one with highest import precedence. But the prepareAttributes() method updates the properties of the mode directly, ignoring this data structure, and the properties are also accessed directly.

#3 Updated by Michael Kay about 4 hours ago

  • Status changed from New to In Progress

I'm tackling this by moving some of the logic for setting properties of a mode from XSLMode.prepareAttributes() to SimpleMode.checkForConflictingProperties().

I'm now getting a couple of test failures because TemplateRule.isDeclaredStreamable() is (apparently) being called before the relevant property of the Mode object has been computed.

#4 Updated by Michael Kay about 4 hours ago

Fixed this by moving the call on ruleManager.checkConsistency() to come earlier in the sequence of tasks performed by PrincipalStylesheetModule.compile().

Now getting xslt30 test failures:

Failures by Test Set: 
  error : 1 (error-0540a)
  match : 3 (-082b, -082c, -260)

#5 Updated by Michael Kay about 3 hours ago

That's now fixed - I overlooked on-multiple-match="fail" in the checkConsistency() logic.

The other thing missing from that code is handling of the visibility attribute. I think that needs some extra tests.

#6 Updated by Michael Kay about 3 hours ago

  • Subject changed from Saxon builds tree although there is an explicit xsl:mode streamable="yes" to Incorrect handling of multiple xsl:mode declarations for the same mode

Please register to edit this issue

Also available in: Atom PDF