XSL中“call-template”和“apply-templates”之间有什么区别?

时间:2010-12-18 12:38:30

标签: xslt apply-templates

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

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

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

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

4 个答案:

答案 0 :(得分:150)

<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属性中定义什么),都要迭代它们( this很重要:apply-templates的工作方式类似于循环!)并找到匹配的模板:

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

这是基本的区别。模板的其他一些方面会影响他们的行为:他们的modepriority,模板可以同时包含namematch。它还会影响模板是否已导入(<xsl:import>)。这些是高级用途,当你到达那里时你可以处理它们。

答案 1 :(得分:15)

要添加@Tomalak的好答案:

以下是一些未提及的重要差异

  1. xsl:apply-templatesxsl:call-templates更丰富更深,甚至来自xsl:for-each只是因为我们不知道将应用哪些代码在节点上 选择 - 在一般情况下,此代码将有所不同 节点列表的不同节点。

  2. 将应用的代码 可以在xsl:apply template写完之后写出来 那些不了解原作者的人。

  3. 如果XSLT没有<xsl:apply-templates>指令,则无法在XSLT中实现FXSL library高阶函数(HOF)

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

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

答案 2 :(得分:6)

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"/> 

这会调用一个名为“nodes”的模板:

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

这与语义不同:

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

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

答案 3 :(得分:2)

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

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

来自MSDN

  

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