Answers:
<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
属性中定义的是什么),都可以对其进行迭代(这很重要: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>
不会改变当前节点。即,.
被调用模板中的指代与.
调用模板中相同的节点。套用范本不是这种情况。
这是基本区别。模板还有其他一些方面会影响它们的行为:mode
和priority
,模板可以同时具有name
和match
。模板是否已导入(<xsl:import>
)也都会产生影响。这些是高级用途,您可以在到达那里时进行处理。
<xsl:apply-templates>
行为就像一个循环。作为XSLT程序员,XSLT处理器端的实现差异不会影响我,对于并行化和迭代实现而言,结果是绝对相同的。但是对于具有强制性背景的XSLT新手来说,它有助于将其设想<xsl:apply-templates>
为一种for-each循环,即使-从技术上来说不是这样。
要添加@Tomalak的良好答案,请执行以下操作:
以下是一些未提及的重要差异:
xsl:apply-templates
xsl:call-templates
xsl:for-each
仅仅因为我们不知道将在选择的节点上应用什么代码,所以它比甚至甚至 更丰富,更深入。--在一般情况下,此代码对于节点列表的不同节点将有所不同。
可以在编写xsl:apply template
s 之后,由不认识原始作者的人来编写将要应用的代码。
如果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
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"/>
...将所有模板应用于名称为“ nodes”的当前XML节点的所有子级。
<xsl:apply-templates>
必须将其实现为循环-相反,它可以并行实现,因为节点列表的不同节点上的不同应用程序是绝对相互独立的。