Project

Profile

Help

Bug #4563

Reuse of Xslt30Transformer causes wrong results (namespace)

Added by Stefan Fritz 2 months ago. Updated 2 months ago.

Status:
New
Priority:
High
Assignee:
-
Category:
-
Sprint/Milestone:
-
Start date:
2020-05-28
Due date:
% Done:

0%

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

Description

Saxon EE 9.8.0.15

If Xslt30Transformer is reused it seems the result of the XSL output changes.

Let me go into more detail: We see this issue with different XSLs but picked one for the reproducible. The XSL removes the namespace from all but the root node.

We have two different input XMLs. The second with namespaces XML1. One without any namespace XML2.

If the Transformer processes the XML2 first and then XML1. The result will be without ANY namespace. It should keep the namespace on root node.

If the Transformer processes the XML1 first and then XML2 and then XML1 again. The result of the first and last transformation will be WITH a namespace on the root node.

Customer uses Java 7 but I reproduced it with Java 8.

This is blocking the customer upgrade project.

Attached is a reproducible. Simply run test01632275.java. The result on stdout is the XML output of the XSL. Line 57 is where you can change which XML to run first.


                        // will cause all output be without any namespace --> WRONG
                        // if(i==0) {

                        // will cause all output 1 and 3 to be with namespace on root node --> CORRECT
                        // if(i==1) {

                        if (i == 0) {
                                xml = xml2;
                        } else {
                                xml = xml1;
                        }
reproducible.zip (1.06 MB) reproducible.zip Stefan Fritz, 2020-05-28 16:17

History

#1 Updated by Michael Kay 2 months ago

Thanks, will investigate.

As a workaround I would suggest creating a new Xslt30Transformer for each transformation. Reusing an Xslt30Transformer is supposed to work, but there is no performance benefit in doing so.

#2 Updated by Stefan Fritz 2 months ago

Thanks for the swift reply. So instead of caching the Transformer we cache the XsltExecutable (as the compile is where we can save time). Then do this on every transform:

Xslt30Transformer trans = s_exp.load30();

Quick test shows that this indeed avoids the problem on the reproducible. Have to run our product test suites to see if it causes other issues.

#3 Updated by Michael Kay 2 months ago

Bug #4019 discusses this issue.

In comment #7 it states "With the Xslt30Transformer we don't have the same complications because we disallow serial reuse." However, I can't see where it is disallowed. The Javadoc (in 10.0) states "It is safe, however, to reuse the object within a single thread to run the same stylesheet several times."

Complicating matters further, if I run your test under 10.0, it fails saying that there is no global context item (it requires one because the global variable $root uses it). If I change the Java code to set a global context item, then the attempt to set the global context item after the first transformation fails saying "Stylesheet has already been evaluated". This is consistent with the documentation for setGlobalContextItem(), which states that an exception is thrown "if the transformation has already been evaluated by calling one of the methods applyTemplates, callTemplate, or callFunction". There are similar rules for the setStylesheetParameters() method. This implies that although the Xslt30Transformer might be serially reusable, the global context item and stylesheet parameters cannot be changed between invocations.

The difference in 9.8 is that the Xslt30Transformer.applyTemplates() method sets the global context item implicitly. This isn't correct according to the XSLT 3.0 specification (which was published on the same day that 9.8 was released), and I don't think it was intended behaviour.

Given that we addressed this issue in 9.9 via Bug #4019, and given that it's all something of a can of worms, I'm a little reluctant to investigate too closely exactly why 9.8 is behaving the way it is. Creating a new Xslt30Transformer for each transformation is definitely the recommended way to go.

#4 Updated by Michael Kay 2 months ago

  • Fix Committed on Branch 10, 9.9 added

I have committed some improvements to the Javadoc on the 9.9 and 10 branches.

#5 Updated by Stefan Fritz 2 months ago

Sounds good. As long as the provided workaround does not cause other issues I think we can close this.

Thanks again for jumping on this so quickly.

#6 Updated by Debbie Lockett 2 months ago

Regenerated Javadoc committed on 9.9 and 10 branches, and updated online (XML and HTML versions).

Please register to edit this issue

Also available in: Atom PDF