Bug #2235
closed@expand-text ignored because XSLT 3.0 not enabled
100%
Description
"When I'm running an XSLT 3.0 stylesheet that uses the @expand-text attribute(text value templates), I get the message above. Running the same transformation, but with -xslversion:3.0 option specified, the value templates are expanded in the text nodes as I expected."
The theory is: you get an XSLT 3.0/2.0 processor if you request it on the command line or the XsltCompiler API, and if you say nothing, the decision is based on the version attribute of the top-level stylesheet or package. This determines the processor version, which is not the same as the effective version of instructions in the stylesheet, which is always determined by the nearest enclosing version attribute. XSLT 3.0 syntax (such as expand-text) is:
-
accepted by an XSLT 3.0 processor, irrespective of the [xsl:]version attribute
-
accepted and ignored by an XSLT 2.0 processor in forwards compatible mode, (i.e. when [xsl:]version="3.0")
-
rejected by an XSLT 2.0 processor if [xsl:]version="2.0"
I think this is being done correctly for processing that happens once the stylesheet tree has been constructed, but it is not working correctly when decisions are made (e.g. for static variables or use-when) during tree construction. The expand-text attribute is (for some reason) being processed during tree construction.
Updated by Michael Kay about 10 years ago
- Status changed from New to In Progress
XSLT Version information is pretty widely scattered. Here's the result of a survey:
On StyleElement, version, and the getEffectiveVersion() method, return the value of the [xsl:]version attribute on the nearest ancestor element that has such an attribute.
On StylesheetPackage, version and getVersion() are the value of the version attribute on the root xsl:package or xsl:stylesheet element.
On CompilerInfo, xsltVersion and getXsltVersion() give the requested processor version: 0.0 meaning no specific version requested, or 2.0 or 3.0. If no specific version was requested, then the value is set to the actual value of the version attribute on the root element of the stylesheet as soon as it is read. (This seems a dubious thing to do: can't a CompilerInfo object be reused for multiple compilations?)
On Compilation, stylesheetVersion and getStylesheetVersion give the actual value of the version attribute on the root element of the stylesheet. As far as I can see, this is set when processing the root element of any stylesheet module, which seems wrong, because an included/imported module is processed using the same Compilation object as its includer/importer.
On StyleNodeFactory, processorVersion and getProcessorVersion give the same as CompilerInfo.getXsltVersion(), provided that the StyleNodeFactory was obtained from the Compilation object. (In other cases, it generally returns null).
On StyleElement, the method isXslt30Processor (which is what we are calling on this path) calls StyleElement.getProcessorVersion(), which constructs a new StyleNodeFactory from the Compilation object, and returns the value of getProcessorVersion() on this StyleNodeFactory; this therefore gives the result of getXsltVersion() on the CompilerInfo.
Updated by Michael Kay about 10 years ago
To make this all more coherent, I am making the following changes:
-
Ensure the StyleNodeFactory always has a reference to a Compilation by making this part of the constructor (and the factory method in the Configuration class)
-
The StyleNodeFactory does not keep a version number of its own, but gets it from the Compilation.
-
In TemplatesHandlerImpl.getTemplates(), remove redundant code which constructs a CompilerInfo object which is then not used.
-
The CompilerInfo holds the requested XSLT version (0 meaning no request) and this is not changed when a version attribute is encountered. The Compilation holds an XSLT version number which is initially that of the CompilerInfo, but changes if it is 0 based on the first version attribute encountered.
-
StyleElement.getProcessorVersion() no longer creates a (quite unecessary) StyleNodeFactory, but simply returns the result of compilation.getVersion()
The above changes fix the problem; now they need regression testing.
Updated by Michael Kay about 10 years ago
With the above changes, unit test testCallNamedTemplateWithParams fails saying initial template parameters cannot be supplied because it's not a 3.0 stylesheet. This is based on the value of Executable.isAllowXPath30() which is returning false. Fixed this by changing the constructor of PreparedStylesheet to use the version from the Compilation rather than the CompilerInfo.
Updated by Michael Kay about 10 years ago
I now get a failure with tests for forwards compatibility. If xsl:stylesheet/@version = "8.5", then Compilation.getVersion()="8.5". The rule should be that xsl:stylesheet/@version determines the XSLT processor version only if the value is 2.0 or 3.0. I think I'll make the rule: if @version="3.0", you get a 3.0 processor, otherwise you get a 2.0 processor.
Updated by Michael Kay about 10 years ago
- Category set to XSLT conformance
- Status changed from In Progress to Resolved
- Found in version set to 9.6
I am now satisfied with the patch and am committing it on the 9.6 and 9.7 branches.
Updated by O'Neil Delpratt about 10 years ago
- Status changed from Resolved to Closed
- % Done changed from 0 to 100
- Fixed in version set to 9.6.0.3
Bug fix patch applied to the Saxon 9.6.0.3 maintenance release
Updated by O'Neil Delpratt about 9 years ago
- Sprint/Milestone set to 9.6.0.3
- Applies to branch 9.6 added
- Fix Committed on Branch 9.6 added
- Fixed in Maintenance Release 9.6.0.3 added
Please register to edit this issue