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

Ven*_*kat 116 xslt apply-templates

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

<xsl:apply-templates name="nodes">
Run Code Online (Sandbox Code Playgroud)

<xsl:call-template select="nodes"> 
Run Code Online (Sandbox Code Playgroud)

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

Tom*_*lak 161

<xsl:call-template> 与传统编程语言中的函数调用相当.

您可以在XSLT中定义函数,就像输出字符串的简单函数一样.

<xsl:template name="dosomething">
  <xsl:text>A function that does something</xsl:text>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

可以通过调用此函数<xsl:call-template name="dosomething">.

<xsl:apply-templates>有点不同,它是XSLT的真正强大之处:它需要任意数量的XML节点(无论你在select属性中定义什么),迭代它们(这很重要: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>
Run Code Online (Sandbox Code Playgroud)

这样你就放弃了对XSLT处理器的一点控制 - 不是你决定程序流的去向,而是处理器通过找到它当前处理的节点的最合适的匹配来做.

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

您可以更专注于开发模板,并且需要更少的时间来进行"管道".您的程序将变得更强大,更模块化,嵌套更少,速度更快(因为XSLT处理器针对模板匹配进行了优化).

使用XSLT理解的概念是"当前节点".随着<xsl:apply-templates>当前节点与每个迭代上移动,而<xsl:call-template>不会改变当前节点.即,.在被调用模板中引用.与调用模板中相同的节点.apply-templates不是这种情况.

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

  • @Dimitre:我想说的是:从最终用户的角度来看,`<xsl:apply-templates>`就像一个循环.XSLT处理器端的实现差异不会影响我作为XSLT程序员,对于并行化和迭代实现来说,结果完全相同.但是对于具有强制性背景的XSLT新手来说,将"<xsl:apply-templates>"设想为一种for-each循环是有帮助的,即使 - 从技术上讲 - 它不是. (8认同)
  • @Tomalak:很好的答案!但是,声明:"xsl:apply-templates是一个循环"是不正确的.在任何官方W3C规范中都没有迹象表明`<xsl:apply-templates>`必须实现为循环 - 相反,它*可以*并行实现,因为不同节点上的不同应用程序node-list完全相互独立. (5认同)

Dim*_*hev 15

要添加@Tomalak的好答案:

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

  1. xsl:apply-templates也更加丰富,比更深xsl:call-templates,甚至从 xsl:for-each,只是因为我们不知道什么代码将选择的节点上应用-在一般情况下,该代码将是节点列表的不同节点不同.

  2. 将要应用的代码可以在编写xsl:apply templates 之后以及不知道原始作者的人员的方式编写.

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

简介:模板和<xsl:apply-templates>指令是XSLT如何实现和处理多态的.

参考:请参阅此完整主题:http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200411/msg00546.html


TTo*_*oni 7

xsl:apply-templates通常(但不一定)用于使用所有适用的模板处理当前节点的所有子集或子集.这支持XSLT应用程序的递归,该应用程序匹配处理的XML的(可能的)递归.

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

所以我使用,xsl:apply-templates如果我想拦截一个有趣的节点的处理,并(通常)注入一些东西到输出流.典型(简化)的例子是

<xsl:template match="foo">
  <bar>
    <xsl:apply-templates/>
  </bar>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

xsl:call-template我通常会解决诸如将一些子节点的文本添加到一起,将选择的节点集转换为文本或其他节点集之类的问题 - 您将为其编写专用的,可重用的函数.

编辑:

作为对特定问题文本的补充说明:

<xsl:call-template name="nodes"/> 
Run Code Online (Sandbox Code Playgroud)

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

    <xsl:template name="nodes">...</xsl:template>
Run Code Online (Sandbox Code Playgroud)

这是一个不同的语义:

<xsl:apply-templates select="nodes"/>
Run Code Online (Sandbox Code Playgroud)

...将所有模板应用于当前XML节点的所有子节点,其名称为"节点".