如何将 XSLT 2 样式表模块中定义的函数公开给 fn:transform?
How to expose functions defined in XSLT 2 stylesheet module to fn:transform?
XPath 3.1 transform
函数允许您应用模板或调用命名模板或调用样式表函数。
但是,当我尝试使用现有的 XSLT 2.0 样式表模块(例如,http://www.xsltfunctions.com/ and available as XSLT 2 at http://www.xsltfunctions.com/xsl/functx-1.0-doc-2007-01.xsl 中记录的 functx 模块)时,在 xsl:stylesheet
中以 XSLT 2 方式声明了许多函数或 xsl:transform
根元素,但不使用 XSLT 3 xsl:package
构造,我无法说服 Saxon 9.8 或 9.9 运行 使用 transform
函数声明的任何函数并使用 initial-function
参数,因为我总是收到错误消息“XTDE0041
:无法从外部调用函数 foo#2,因为它不是 public”。
示例可能是:
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
但给出上述错误。
我发现的唯一解决方法是动态构建(例如在 XQuery 中)一个 XSLT 3 包,导入 functx 模块并使用 xsl:expose
生成函数 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
这可行,但需要使用 XPath 3.1 的宿主语言(如上面的 XQuery 3.1)。
有没有更简单的方法来使用 transform
函数和 initial-function
以及声明函数的现有 XSLT 2 样式表模块?
根据 Michael Kay 在 https://saxonica.plan.io/boards/3/topics/7540 中的解释,任何没有 visibility
属性的命名函数在默认情况下都被执行样式表的 fn:transform
函数视为私有,无论该函数是否出现在显式包或隐式包(即带有 xsl:stylesheet
或 xsl:transform
的样式表模块)。
基于此,确实需要重写 XSLT 2 代码以添加 visibility
应该可由 fn:transform
执行调用的函数属性,或者需要 "wrap" 现有 XSLT 2 代码到允许更改可见性的 XSLT 3 构造中,就像我在尝试使用 xsl:import
导入 XSLT 2 代码并使用 xsl:expose
确保导入函数时所做的那样 public 例如<xsl:expose component="function" names="functx:*" visibility="public"/>
。然而,除了 XPath 3.1 fn:transform
.
之外,后者还需要使用 XSLT 3 或 XQuery 3
XPath 3.1 transform
函数允许您应用模板或调用命名模板或调用样式表函数。
但是,当我尝试使用现有的 XSLT 2.0 样式表模块(例如,http://www.xsltfunctions.com/ and available as XSLT 2 at http://www.xsltfunctions.com/xsl/functx-1.0-doc-2007-01.xsl 中记录的 functx 模块)时,在 xsl:stylesheet
中以 XSLT 2 方式声明了许多函数或 xsl:transform
根元素,但不使用 XSLT 3 xsl:package
构造,我无法说服 Saxon 9.8 或 9.9 运行 使用 transform
函数声明的任何函数并使用 initial-function
参数,因为我总是收到错误消息“XTDE0041
:无法从外部调用函数 foo#2,因为它不是 public”。
示例可能是:
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
但给出上述错误。
我发现的唯一解决方法是动态构建(例如在 XQuery 中)一个 XSLT 3 包,导入 functx 模块并使用 xsl:expose
生成函数 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
这可行,但需要使用 XPath 3.1 的宿主语言(如上面的 XQuery 3.1)。
有没有更简单的方法来使用 transform
函数和 initial-function
以及声明函数的现有 XSLT 2 样式表模块?
根据 Michael Kay 在 https://saxonica.plan.io/boards/3/topics/7540 中的解释,任何没有 visibility
属性的命名函数在默认情况下都被执行样式表的 fn:transform
函数视为私有,无论该函数是否出现在显式包或隐式包(即带有 xsl:stylesheet
或 xsl:transform
的样式表模块)。
基于此,确实需要重写 XSLT 2 代码以添加 visibility
应该可由 fn:transform
执行调用的函数属性,或者需要 "wrap" 现有 XSLT 2 代码到允许更改可见性的 XSLT 3 构造中,就像我在尝试使用 xsl:import
导入 XSLT 2 代码并使用 xsl:expose
确保导入函数时所做的那样 public 例如<xsl:expose component="function" names="functx:*" visibility="public"/>
。然而,除了 XPath 3.1 fn:transform
.