Bug #3333
closedUsing an XSLT 3.0 package indirectly by several routes
100%
Description
I'd like to be able to create a single package of common functions, variables, etc.
Something like this:
<xsl:package
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
name="http://www.oup.com/oup-academic-common-package"
package-version="0.1"
version="3.0">
<xsl:use-package name="http://www.oup.com/logger" package-version="0.1"/>
<xsl:use-package name="http://www.oup.com/generalVariables" package-version="0.1"/>
<xsl:use-package name="http://www.oup.com/getDTD" package-version="0.1"/>
</xsl:package>
Both "logger" and "getDTD" packages need to use the "generalVariables" package.
The "generalVariables" package also needs to be available to the stylesheet that uses the "oup-academic-common-package".
My first attempt threw up duplicate variable error messages.
Then I had a go with xsl:accept. So now both the "logger" and "getDTD" packages contain this statement:
<xsl:use-package name="http://www.oup.com/generalVariables" package-version="0.1">
<xsl:accept component="*" names="*" visibility="private"/>
</xsl:use-package>
Now my error message is:
java.lang.AssertionError: Saxon can't find the new component corresponding to variable oupdtg:filePathSeparator
oupdtg:fileSeparator is a variable defined in the "generalVariables" package:
<xsl:package
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
xmlns:oupdtg="http://www.oup.com/oupdtg"
name="http://www.oup.com/generalVariables"
package-version="0.1"
exclude-result-prefixes="#all"
version="3.0">
<xsl:variable name="oupdtg:newLine" as="xs:string" visibility="public">
<xsl:text>
</xsl:text>
</xsl:variable>
<xsl:variable name="oupdtg:quot" as="xs:string" visibility="public" select="'"'"/>
<xsl:variable name="oupdtg:filePathSeparator" as="xs:string" visibility="public" select="'[\\/]'"/>
</xsl:package>
If I use the three packages directly within my stylesheet (rather than wrapping them in the "oup-academic-common-package", the stylesheet works fine.
But is it possible to create this wrapper package?
Files
Related issues
Updated by Michael Kay over 7 years ago
I think I need to see the source code (or a repro that demonstrates the problem) to understand what's going on here.
If something is public in generalVariables then it should become private within the packages that use it, so this conflict shouldn't happen -- in theory.
The code in this area hasn't had a large amount of exposure except to synthetic small-scale test cases so my instinct is to suspect a bug somewhere: in which case I will need a repro to investigate.
Updated by Mark Dunn over 7 years ago
- File test-packages.zip test-packages.zip added
I've attached a set of files with two top-level stylesheets, which illustrate a couple of scenarios.
test-xslt3-packages-1.xsl¶
Uses "oup-academic-common-package", which uses "logger", "generalFunctions", "generalVariables", and "runner".
"logger" uses "generalVariables"
"generalFunctions" uses "generalVariables"
Error message:
javax.xml.transform.TransformerConfigurationException: net.sf.saxon.s9api.SaxonApiException: Duplicate variable oupdtg:city
test-xslt3-packages-2.xsl¶
Uses "runner", which uses "logger" and "generalFunctions".
Error message:
java.lang.AssertionError: Saxon can't find the new component corresponding to variable oupdtg:city
Also included is an Ant build file and a batch file which I used to run the transformations using Saxon 9.8 HE. The error messages were the same using both methods of running the transformations.
Updated by Michael Kay over 7 years ago
Sorry for the delay in responding. I've added some internal tracing to the code to show what's going on (it would seem a good idea to productize this). For the first case (packages-1) we have
Adding components from http://www.oup.com/generalVariables to http://www.oup.com/logger
variable oupdtg:city (PUBLIC) becomes PRIVATE
mode xsl:unnamed (PRIVATE) becomes HIDDEN
Adding components from http://www.oup.com/generalVariables to http://www.oup.com/generalFunctions
variable oupdtg:city (PUBLIC) becomes PRIVATE
mode xsl:unnamed (PRIVATE) becomes HIDDEN
Adding components from http://www.oup.com/logger to http://www.oup.com/runner
template oupdtg:log (PUBLIC) becomes PRIVATE
variable oupdtg:city (PRIVATE) becomes HIDDEN [1]
mode xsl:unnamed (PRIVATE) becomes HIDDEN
Adding components from http://www.oup.com/generalFunctions to http://www.oup.com/runner
variable oupdtg:city (PRIVATE) becomes HIDDEN
function oupdtg:getCity#0 (PUBLIC) becomes PRIVATE
mode xsl:unnamed (PRIVATE) becomes HIDDEN
Adding components from http://www.oup.com/logger to http://www.oup.com/oup-academic-common-package
template oupdtg:log (PUBLIC) becomes PRIVATE
variable oupdtg:city (PRIVATE) becomes HIDDEN
mode xsl:unnamed (PRIVATE) becomes HIDDEN
Adding components from http://www.oup.com/generalFunctions to http://www.oup.com/oup-academic-common-package
variable oupdtg:city (PRIVATE) becomes HIDDEN
function oupdtg:getCity#0 (PUBLIC) becomes PRIVATE
mode xsl:unnamed (PRIVATE) becomes HIDDEN
Adding components from http://www.oup.com/generalVariables to http://www.oup.com/oup-academic-common-package
variable oupdtg:city (PUBLIC) becomes PRIVATE
mode xsl:unnamed (PRIVATE) becomes HIDDEN
Adding components from http://www.oup.com/runner to http://www.oup.com/oup-academic-common-package
template oupdtg:log (PRIVATE) becomes HIDDEN
variable oupdtg:city (PUBLIC) becomes PRIVATE [2]
Error at procedure oupdtg:city on line 19 of generalVariables.xsl:
XTSE3050: Duplicate variable oupdtg:city
Duplicate variable oupdtg:city
Messages labelled [1] and [2] appear to show a contradiction - the variable should be HIDDEN in runner, and therefore remain HIDDEN in academic-common.
Updated by Michael Kay over 7 years ago
What's happening here is specific to global variables (as distinct from other kinds of component). After collecting together all the components acquired from a used package, we allocate slot numbers for space allocation in the Bindery for the package (StylesheetPackage.allocateBinderySlots()). This invokes the method registerGlobalVariable(), which has the side-effect of creating a PUBLIC global variable with the requisite name. This is clearly incorrect.
I'm concerned about another couple of things noticed while analyzing this:
(a) where a package acquires two hidden components with the same name from different packages, they are being merged into one. This seems wrong. The merging happens because StylesheetPackage.hiddenComponents is a map keyed on symbolic name.
(b) the process of acquiring components from a used package seems to ignore hidden components in the used package.
Updated by Michael Kay over 7 years ago
- Tracker changed from Support to Bug
- Category set to XSLT 3.0 packages
- Status changed from New to In Progress
- Assignee set to Michael Kay
- Priority changed from Low to Normal
- Applies to branch 9.8 added
Updated by Michael Kay over 7 years ago
- Subject changed from Can I create a package containing a hierarchy of used packages? to Using an XSLT 3.0 package indirectly by several routes
Updated by Michael Kay over 7 years ago
I've fixed the problems identified above, and compilation of packages-1.xsl now fails with
Static error in {oupdtg:getCity()} in expression in xsl:copy-of/@select on line 16 column 53 of test-xslt3-packages-1.xsl:
XPST0017: Cannot find a matching 0-argument function named {http://www.oup.com/oupdtg}getCity()
Static error at xsl:call-template on line 15 column 51 of test-xslt3-packages-1.xsl:
XTSE0650: No template exists named oupdtg:log
which is correct, because these components are private in common-package and therefore hidden in packages-1.
Adding
<xsl:expose component="*" names="*" visibility="public"/>
to common-package doesn't help because the components are private in common-package and therefore cannot be exposed as public. Instead I need to insert an xsl:accept element into each xsl:use-package, in the form
<xsl:accept component="*" names="*" visibility="public"/>
after which I get the (presumably) correct result
<output><log>Oxford</log><city>Oxford</city></output>
Updated by Michael Kay over 7 years ago
Confirmed that the above changes cause no regression in test-sets package, use-package, expose, accept, or override.
Updated by Michael Kay over 7 years ago
The second test, test-packages-2, also runs successfully after making these changes.
Updated by Mark Dunn over 7 years ago
That's the correct output, and adding the xsl:accept/ statement to common-package to produce it makes sense to me.
Glad to be of help flushing out this issue!
Updated by Michael Kay over 7 years ago
- Status changed from In Progress to Resolved
Updated by O'Neil Delpratt over 7 years ago
- Has duplicate Bug #3367: function not found inside xslt package added
Updated by O'Neil Delpratt over 7 years ago
- % Done changed from 0 to 100
- Fix Committed on Branch 9.8 added
Updated by O'Neil Delpratt over 7 years ago
- Status changed from Resolved to Closed
- Fixed in Maintenance Release 9.8.0.4 added
Bug fix applied in the Saxon 9.8.0.4 maintenance release.
Please register to edit this issue