125

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

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

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

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

4

4 回答 4

176

<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属性中定义什么),处理每个节点(不一定按任何预定义的顺序),有人可以说应用模板像循环一样工作,但情况并非如此,因为节点可以按任何顺序处理,甚至并行处理,并为它们找到匹配的模板:

<!-- 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>不会改变当前节点。即,被调用模板中的 与调用模板.中的 相同.。应用模板不是这种情况。

这是基本的区别。模板还有一些其他方面会影响它们的行为:它们的mode和,模板可以同时具有 a和 apriority的事实。模板是否已导入 ( ) 也有影响。这些是高级用途,您可以在到达那里时处理它们。namematch<xsl:import>

于 2010-12-18T13:02:25.997 回答
16

补充@Tomalak的好答案:

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

  1. xsl:apply-templatesxsl:call-templates甚至 from 更丰富、更深入xsl:for-each仅仅是因为我们不知道将在选择的节点上应用什么代码——在一般情况下,对于节点列表的不同节点,此代码会有所不同。

  2. 将要应用的代码可以在写完xsl:apply templates之后由不知道原作者的人编写。

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

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

参考:查看整个线程: http: //www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200411/msg00546.html

于 2010-12-18T17:38:31.140 回答
9

xsl:apply-templates通常(但不一定)用于处理具有所有适用模板的当前节点的所有子节点或子节点的子集。这支持 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 节点的所有子节点,其名称为“nodes”。

于 2010-12-18T13:08:12.217 回答
2

功能确实相似(除了调用语义,call-template需要name属性和相应的名称模板)。

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

来自MSDN

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

于 2010-12-18T12:42:52.387 回答