XSL中的“call-template”和“apply-templates”有什么区别?
我是XSLT新手,所以我对这两个标签有点困惑,
<xsl:apply-templates name="nodes">
和
<xsl:call-template select="nodes">
那么你能列出它们之间的区别吗?
<xsl:call-template>
与以传统编程语言调用函数相当接近。
您可以在XSLT中定义函数,就像这个输出string的简单函数一样。
<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节点(不pipe你在select
属性中定义了什么),迭代它们( 这很重要:apply-templates的工作方式就像一个循环! )并find匹配的模板:
<!-- 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处理器的一些控制 – 不是您决定程序stream向何处,而是处理器通过为当前正在处理的节点find最合适的匹配。
如果多个模板可以匹配节点,则具有更具体匹配expression式的模板将胜出。 如果存在多个具有相同特异性的匹配模板,则声明最后一个的模板胜出。
您可以更专注于开发模板,并且需要更less的时间来完成“水暖工”。 您的程序将变得更加强大和模块化,嵌套更less,速度更快(因为XSLT处理器针对模板匹配进行了优化)。
用XSLT理解的概念是“当前节点”。 使用<xsl:apply-templates>
,当前节点每次迭代都会继续,而<xsl:call-template>
不会更改当前节点。 也就是说.
在一个被调用的模板内引用与之相同的节点.
在通话模板中。 apply-templates不是这种情况。
这是基本的区别。 模板的其他方面也会影响其行为: mode
和priority
,模板可以同时具有name
和match
。 它也影响模板是否已被导入( <xsl:import>
)或不。 这些是先进的用途,你可以在你到达时处理它们。
要添加到@Tomalak的好回答:
以下是一些未提及的重要区别 :
-
xsl:apply-templates
比xsl:call-templates
甚至来自xsl:for-each
要丰富和深入,因为我们不知道在select的节点上应用什么代码 – 在一般情况下代码对于节点列表的不同节点将是不同的。 -
在写入
xsl:apply template
之后,以及不知道原始作者的人可以使用将要应用的代码 。
如果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
通常(但不一定)用于处理当前节点的所有子节点或子节点以及所有适用的模板。 这支持与正在处理的XML的(可能的)recursion匹配的XSLT应用程序的recursion。
另一方面, xsl:call-template
更像是一个普通的函数调用。 您只需执行一个(命名)模板,通常使用一个或多个参数。
所以我使用xsl:apply-templates
如果我想拦截一个有趣的节点的处理和(通常)注入的东西到输出stream。 典型的(简化的)例子是
<xsl:template match="foo"> <bar> <xsl:apply-templates/> </bar> </xsl:template>
而对于xsl:call-template
我通常会解决一些问题,比如将一些子节点的文本添加到一起,将select的节点集合转换为文本或其他节点集合等等 – 任何你想写的专门的,可重用的函数。
编辑:
作为对您的具体问题文本的补充评论:
<xsl:call-template name="nodes"/>
这将调用一个名为“节点”的模板:
<xsl:template name="nodes">...</xsl:template>
这是一个不同的语义:
<xsl:apply-templates select="nodes"/>
…将所有模板应用于当前名为“节点”的XML节点的所有子节点。
function确实类似(除了调用语义,其中call-template
需要name
属性和相应的名称模板)。
但是,parsing器不会以相同的方式执行。
来自MSDN :
与
<xsl:apply-templates>
,<xsl:call-template>
不会更改当前节点或当前节点列表。