Reputation: 167716
The XPath 3.1 transform
functions allows you to apply templates or call a named template or call a stylesheet function.
However, when I try to use an existing XSLT 2.0 stylesheet module (like, for instance, the functx module documented at http://www.xsltfunctions.com/ and available as XSLT 2 at http://www.xsltfunctions.com/xsl/functx-1.0-doc-2007-01.xsl) declaring lots of functions the XSLT 2 way within an xsl:stylesheet
or xsl:transform
root element, but not using the XSLT 3 xsl:package
construct, I can't convince Saxon 9.8 or 9.9 to run any of the declared functions with the transform
function and with the initial-function
argument as I always get an error "XTDE0041
: Cannot invoke function foo#2 externally, because it is not public".
Example could would be:
transform(
map {
'stylesheet-location': 'http://www.xsltfunctions.com/xsl/functx-1.0-doc-2007-01.xsl',
'delivery-format': 'raw',
'initial-function': QName('http://www.functx.com', 'substring-before-match'),
'function-params': ['abc-def-ghi', '[dg]']
})?output
but gives above cited error.
The only workaround I found is to construct (for example in XQuery) an XSLT 3 package on the fly importing the functx module and using xsl:expose
to make the functions public:
let $functxNs := 'http://www.functx.com',
$functxLoc := 'http://www.xsltfunctions.com/xsl/functx-1.0-doc-2007-01.xsl',
$libPackage := <xsl:package
name="http://example.com/import-functx"
package-version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:functx="http://www.functx.com">
<xsl:expose
component="function"
names="functx:*"
visibility="public"/>
<xsl:import
href="{$functxLoc}"/>
</xsl:package>
return
transform(
map {
'stylesheet-node': $libPackage,
'delivery-format': 'raw',
'initial-function': QName('http://www.functx.com', 'substring-before-match'),
'function-params': ['abc-def-ghi', '[dg]']
})?output
This works but requires using a host language to XPath 3.1 (like XQuery 3.1 above).
Is there any easier way to use the transform
function and initial-function
with existing XSLT 2 stylesheet modules declaring functions?
Upvotes: 0
Views: 279
Reputation: 167716
Based on Michael Kay's explanatations in https://saxonica.plan.io/boards/3/topics/7540 any named function without a visibility
attribute is by default considered private by the fn:transform
function executing a stylesheet, whether the function appears in an explicit package or in an implicit one (i.e. a stylesheet module with xsl:stylesheet
or xsl:transform
).
Based on that one indeed needs to rewrite XSLT 2 code to add visibility
attributes for functions supposed to be callable by an fn:transform
execution or one needs to "wrap" the existing XSLT 2 code into an XSLT 3 construct that allows changing the visibility, like I did in my attempt to import the XSLT 2 code with xsl:import
and to use xsl:expose
to ensure the imported functions are made public by e.g. <xsl:expose component="function" names="functx:*" visibility="public"/>
. The latter however requires use of XSLT 3 or XQuery 3 in addition to XPath 3.1's fn:transform
.
Upvotes: 0