只有 name 属性的 xsl:template 和 xsl:function 有啥区别

Posted

技术标签:

【中文标题】只有 name 属性的 xsl:template 和 xsl:function 有啥区别【英文标题】:What are the differences between xsl:template which has only name attribute and xsl:function只有 name 属性的 xsl:template 和 xsl:function 有什么区别 【发布时间】:2020-04-03 11:08:49 【问题描述】:

我发现它们都可以用参数调用并返回xsl:value-ofxsl:sequence,但有什么区别?在什么情况下应该使用一个而不是另一个更好?大量使用时会出现性能问题吗?

非常感谢。

顺便说一句:我的 XSLT 处理器是 saxon-he 9.8+。

【问题讨论】:

xsl:template 在 XSL 1.0 中受支持,xsl:function 不支持。 xsl:template 只能用call-template 调用,xsl:function 可以出现在表达式中。 突然想到有一个关键字“tunnel”只能用在模板的参数中,不能用在函数的参数中。他的使用是否只对被调用的后代模板可见? 【参考方案1】:

一些更重要的区别是:

只能在模板中创建辅助结果文档,而不能在函数中创建,请参阅https://www.w3.org/TR/xslt-30/#result-document-restrictions 指定“[ERR XTDE1480] 在临时输出状态下评估xsl:result-document 指令是一个动态错误。”和 "xsl:variable、xsl:param、xsl:with-param、xsl:function、xsl:key、xsl:sort、xsl:accumulator-rule 和 xsl:merge-key 总是在它们包含的序列构造函数中评估指令临时输出状态”。 在函数体内部,焦点(上下文项、上下文位置、上下文大小)最初不存在(请参阅https://www.w3.org/TR/xslt-30/#function-result 指定“在序列构造函数中,焦点最初不存在;这意味着任何引用上下文项、上下文位置或上下文大小是动态错误”),这意味着,任何未存储在全局变量中的项都需要作为参数传递给函数 在 Saxon(至少为 9.8 和 9.9)中,虽然 API (http://saxonica.com/html/documentation/javadoc/net/sf/saxon/s9api/Xslt30Transformer.html#callFunction-net.sf.saxon.s9api.QName-net.sf.saxon.s9api.XdmValue:A-) 已扩展为支持新的 XSLT 3 功能以通过调用命名(和公共)函数来开始处理,但命令行界面不不允许这样做,因为它没有新的命令行选项

【讨论】:

谢谢,他们太专业了。请问,对于第一项的第二句,是否意味着“:xsl:variable, ... xsl:merge-key”在模板和函数中的使用方式相同?遗憾的是最后一项,我不知道,不明白什么情况下使用API​​ callFunction\callTemplate。 我提到的第三点是指 XSLT 3 规范为您提供启动/调用转换的选项,它提到了“应用模板调用”(w3.org/TR/xslt-30/#invoking-initial-mode)、“调用模板调用” " (w3.org/TR/xslt-30/#invoking-initial-template) 和 "函数调用调用" (w3.org/TR/xslt-30/#invoking-initial-function)。与 Java 或 C# 一起使用的 API 级别的 Saxon 9(9.8 和 9.9)为您提供了所有三个选项,但在命令行中只有前两个选项。 我引用的那句话提到xsl:variable, xsl:param, ..., xsl:merge-key 确实表明在所有这些中使用xsl:result-document 来创建辅助结果文档是行不通的。 我看到这句话了,谢谢。第三点,我也理解,但是我还有一个问题,c/c++ saxon版本可以使用“调用模板调用”、“函数调用调用”吗? 当然,saxonica.com/saxon-c/doc/html/classXslt30Processor.html 的 API 文档有 callTemplateReturningFile/callTemplateReturningString/callTemplateReturningValuecallFunctionReturningFile/callFunctionReturningString/callFunctionReturningValue 等相关方法。【参考方案2】:

恕我直言,有几个区别:

您可以在 XPath 中使用 XSL 函数。这是模板无法做到的。 您需要显式调用函数。隐式应用模板(不需要call-template) 早期版本的 XSL 支持模板

关于性能:在您发现性能问题之前不要打扰。正如 Donald Knuth 所说:“过早的优化是万恶之源”。只需使用最适合该目的的任何东西。

【讨论】:

Templates are applied implicitly - 不是只有name的那些,只能是call-templated。 当我们翻译当前元素及其后代时,哪个是更好的选择? @cmf41013:我更喜欢模板,但可能是我更习惯了。【参考方案3】:

XSLT 是一种两种语言的系统; XSLT 和 XPath 共享相同的数据模型,但它们不是完全可组合的。您可以在 XSLT 指令中嵌套 XPath 表达式,但不能反过来。

为了弥补可组合性的不足,许多“控制流”操作在两种语言中重复。 XSLT 有条件指令,XPath 有条件表达式。 XSLT 有一个映射运算符 (xsl:for-each),XPath 也有 (!)。 XSLT 可以声明变量(xsl:variable),XPath 也可以(let)。 XSLT 有一个调用机制(xsl:call-template),XPath(函数调用)也有。存在这些重复是为了减少为常见的简单任务在两种语言之间切换的不便。函数调用和命名模板之间的二元性只是一个例子。

更具体地说,xsl:function 是在 XSLT 2.0 中引入的,作为一种允许从 XPath 表达式中调用 XSLT 构造(xsl:numberxsl:sort 是经典示例)的方式,从而提高了两种语言的可组合性,甚至虽然直接的语法嵌套是不可能的。

【讨论】:

这对我来说太深奥了。是不是越频繁地在两种语言之间切换,性能越低? 我似乎明白为什么 xsl:function 出来了。最重要的是,由 xpath 调用以进行跨越? 性能取决于实现。因为这些语言共享相同的数据模型,所以在相互调用一种语言时应该不需要任何运行时开销——尽管如果 XSLT 引擎和 XPath 引擎是独立开发的并且具有不同的内部数据表示,则可能会发生这种情况。

以上是关于只有 name 属性的 xsl:template 和 xsl:function 有啥区别的主要内容,如果未能解决你的问题,请参考以下文章

XSL xsl:template match =“/”

XSL 递归调用 - xsl:functions vs xsl:template with call template

QName

XSL 风格:在 XSLT 中使用 <xsl:for-each select> 或 <xsl:template match> 或其他解决方案?

关于xls的一点笔记

XSL xsl:模板匹配="/"