Bug #4563
closedReuse of Xslt30Transformer causes wrong results (namespace)
100%
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;
}
Files
Updated by Michael Kay over 4 years 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.
Updated by Stefan Fritz over 4 years 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.
Updated by Michael Kay over 4 years 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.
Updated by Michael Kay over 4 years ago
- Fix Committed on Branch 10, 9.9 added
I have committed some improvements to the Javadoc on the 9.9 and 10 branches.
Updated by Stefan Fritz over 4 years 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.
Updated by Debbie Lockett over 4 years ago
Regenerated Javadoc committed on 9.9 and 10 branches, and updated online (XML and HTML versions).
Updated by Michael Kay about 4 years ago
- Category set to s9api API
- Status changed from New to Resolved
- Assignee set to Michael Kay
- Priority changed from High to Normal
Closing this with no further changes.
Updated by O'Neil Delpratt about 4 years ago
- Fixed in Maintenance Release 9.9.1.8 added
Bug fix applied on the Saxon 9.9.1.8 maintenance release. Leaving open until applied on the Saxon 10 maintenance release.
Updated by O'Neil Delpratt about 4 years ago
Bug fix applied in the Saxon 10.3 maintenance release
Updated by O'Neil Delpratt about 4 years ago
- Status changed from Resolved to Closed
- % Done changed from 0 to 100
- Fixed in Maintenance Release 10.3 added
Please register to edit this issue