我是XSLT的新手,所以我对这两个标签感到有些困惑,
<xsl:apply-templates name="nodes">
和
<xsl:call-template select="nodes">
那么你能列出它们之间的区别吗?
答案 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不是这种情况。
这是基本的区别。模板的其他一些方面会影响他们的行为:他们的mode
和priority
,模板可以同时包含name
和match
。它还会影响模板是否已导入(<xsl:import>
)。这些是高级用途,当你到达那里时你可以处理它们。
答案 1 :(得分:15)
要添加@Tomalak的好答案:
以下是一些未提及的重要差异:
xsl:apply-templates
比xsl:call-templates
更丰富更深,甚至来自xsl:for-each
,只是因为我们不知道将应用哪些代码在节点上
选择 - 在一般情况下,此代码将有所不同
节点列表的不同节点。
将应用的代码
可以在xsl:apply template
写完之后写出来
那些不了解原作者的人。
如果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>
不会更改当前节点或当前节点列表。