XSL 中的“ call-template”和“ application-template”有什么区别?

我是 XSLT 的新手,所以对这两个标记有点困惑,

<xsl:apply-templates name="nodes">

还有

<xsl:call-template select="nodes">

你能列出它们之间的区别吗?

119522 次浏览

其功能实际上是相似的(除了调用语义之外,其中 call-template需要 name属性和相应的名称模板)。

但是,解析器不会以相同的方式执行。

来自 MSDN:

<xsl:apply-templates>不同,<xsl:call-template>不更改当前节点或当前节点列表。

<xsl:call-template>非常类似于在传统编程语言中调用函数。

您可以在 XSLT 中定义函数,比如这个输出字符串的简单函数。

<xsl:template name="dosomething">
<xsl:text>A function that does something</xsl:text>
</xsl:template>

这个函数可以通过 <xsl:call-template name="dosomething">调用。

<xsl:apply-templates>有一点不同,它是 XSLT 的真正力量: 它接受任意数量的 XML 节点(不管你在 select属性中定义了什么) ,处理每个节点(不一定按照任何预定义的顺序) ,有人可能会说 application-template 像循环一样工作,但事实并非如此,因为节点可以按任意顺序处理,甚至并行处理,并为它们找到匹配的模板:

<!-- sample XML snippet -->
<xml>
<foo /><bar /><baz />
</xml>


<!-- sample XSLT snippet -->
<xsl:template match="xml">
<xsl:apply-templates select="*" /> <!-- three nodes selected here -->
</xsl:template>


<xsl:template match="foo"> <!-- will be called once -->
<xsl:text>foo element encountered</xsl:text>
</xsl:template>


<xsl:template match="*"> <!-- will be called twice -->
<xsl:text>other element countered</xsl:text>
</xsl:template>

通过这种方式,您可以向 XSLT 处理器放弃一些控制权——不是您决定程序流向何处,而是处理器通过为它当前处理的节点找到最合适的匹配来做到这一点。

如果多个模板可以匹配一个节点,那么具有更具体匹配表达式的模板将获胜。如果存在多个具有相同特异性的匹配模板,则最后声明的模板获胜。

您可以将更多的精力放在开发模板上,并且只需要更少的时间来完成“管道”工作。您的程序将变得更强大、更模块化、嵌套更少、速度更快(因为 XSLT 处理器针对模板匹配进行了优化)。

使用 XSLT 需要理解的一个概念是“当前节点”的概念。对于 <xsl:apply-templates>,当前节点随着每次迭代继续移动,而 <xsl:call-template>不更改当前节点。也就是说,被调用模板中的 .引用与调用模板中的 .相同的节点。Application-template 不是这种情况。

这是最基本的区别。模板还有一些其他方面影响它们的行为: 它们的 modepriority,事实上模板可以同时具有 namematch。它还会影响模板是否已经导入(<xsl:import>)。这些都是先进的用途,你可以处理他们,当你到达那里。

通常(但不一定)使用 所有适用模板处理当前节点的全部或部分子节点。这支持 XSLT 应用程序的递归性,它与处理的 XML 的递归性(可能的)相匹配。

另一方面,xsl:call-template更像是一个普通的函数调用。只执行一个(命名的)模板,通常使用一个或多个参数。

因此,如果我想拦截一个感兴趣节点的处理并(通常)向输出流中注入一些内容,我就使用 xsl:apply-templates。一个典型的(简化的)例子是

<xsl:template match="foo">
<bar>
<xsl:apply-templates/>
</bar>
</xsl:template>

而使用 xsl:call-template,我通常可以解决一些问题,比如将一些子节点的文本添加到一起,将选择的节点集转换为文本或其他节点集,以及类似的任何需要编写专门的、可重用的函数的东西。

编辑:

作为对具体问题文本的补充说明:

<xsl:call-template name="nodes"/>

它调用一个名为“节点”的模板:

    <xsl:template name="nodes">...</xsl:template>

这种语义不同于:

<xsl:apply-templates select="nodes"/>

... 它将所有模板应用于当前名为“节点”的 XML 节点的所有子节点。

作者@Tomalak 给出了更好的回答:

以下是一些未提及的重要区别 :

  1. xsl:apply-templatesxsl:call-templates更加丰富和深入,甚至比 xsl:for-each更加丰富和深入, 仅仅是因为我们不知道在 选择——在一般情况下,这段代码对于 节点列表的不同节点。

  2. 将要应用的代码 可以在 xsl:apply templates 被写入后写入方式 和 by 不认识原作者的人

如果 XSLT 没有 <xsl:apply-templates>指令,那么 FXSL 库在 XSLT 中实现高阶函数(HOF)是不可能的。

摘要 : 模板和 <xsl:apply-templates>指令是 XSLT 实现和处理多态性的方式。

参考文献 : 查看整个帖子: < strong > http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200411/msg00546.html