133

I am new in XSLT so I'm little bit confused about the two tags,

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

and

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

So can you list out the difference between them?

Tomalak
  • 332,285
  • 67
  • 532
  • 628
Venkat
  • 20,802
  • 26
  • 75
  • 84

4 Answers4

184

<xsl:call-template> is a close equivalent to calling a function in a traditional programming language.

You can define functions in XSLT, like this simple one that outputs a string.

<xsl:template name="dosomething">
  <xsl:text>A function that does something</xsl:text>
</xsl:template>

This function can be called via <xsl:call-template name="dosomething">.

<xsl:apply-templates> is a little different and in it is the real power of XSLT: It takes any number of XML nodes (whatever you define in the select attribute), processes each of them (not necessarily in any predefined order), somebody could say that apply-templates works like a loop, but this is not exactly the case, as the nodes may be processed in any order, even in parallel, and finds matching templates for them:

<!-- 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>

This way you give up a little control to the XSLT processor - not you decide where the program flow goes, but the processor does by finding the most appropriate match for the node it's currently processing.

If multiple templates can match a node, the one with the more specific match expression wins. If more than one matching template with the same specificity exist, the one declared last wins.

You can concentrate more on developing templates and need less time to do "plumbing". Your programs will become more powerful and modularized, less deeply nested and faster (as XSLT processors are optimized for template matching).

A concept to understand with XSLT is that of the "current node". With <xsl:apply-templates> the current node moves on with every iteration, whereas <xsl:call-template> does not change the current node. I.e. the . within a called template refers to the same node as the . in the calling template. This is not the case with apply-templates.

This is the basic difference. There are some other aspects of templates that affect their behavior: Their mode and priority, the fact that templates can have both a name and a match. It also has an impact whether the template has been imported (<xsl:import>) or not. These are advanced uses and you can deal with them when you get there.

Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • 5
    @Tomalak: Good answer! However, the statement: "xsl:apply-templates is a loop" isn't correct. There is no indication in any official W3C spec that `` must be implemented as a loop -- on the contrary, it *may* be implemented in parallel, because the different applications on the different nodes of the node-list are absolutely independent from each other. – Dimitre Novatchev Dec 18 '10 at 21:04
  • 9
    @Dimitre: What I meant to say: From an end-user's perspective, `` behaves like a loop. Implementation differences on the XSLT processor's end will not affect me as an XSLT programmer, the outcome is absolutely the same for parallelized and iterative implementations alike. But for an XSLT newbie with an imperative background, it helps to envision `` as a kind of for-each loop, even if - technically - it isn't. – Tomalak Dec 18 '10 at 21:13
  • 1
    @Tomalak: While this may be useful for novice XSLT programmers, I think it is often misleading to them as they think that they can re-use state information accumulated in the "execution of the loop". – Dimitre Novatchev Dec 18 '10 at 21:16
  • @Tomalak: Because of these facts, I think that it would be appropriate to modify "xsl:apply-templates is a loop"with somethinkg like: "xsl:apply-templates is *like* a loop" – Dimitre Novatchev Dec 18 '10 at 21:29
  • @Tomalak: Loop is iteration, something `apply-templates` and `call-template` instructions are not for. They are the recursion mechanism in XSLT. And as Dimitre has answered, apply-templates is the polymorphism or data driven mechanism. –  Dec 19 '10 at 21:08
  • @Alejandro: Neither `apply-templates` nor `call-template` recurse on their own. Without *calling* them recursively, their effect is that of iteration. – Tomalak Dec 19 '10 at 21:23
  • @Tomalak: They might not recurse on their own, but there is no recursion mechanism other than them. –  Dec 19 '10 at 21:52
  • @Tomalak - As user Ben points out in [this question](http://stackoverflow.com/q/15868300/1945651) (I'm posting this on his behalf because he can't post comments yet), the behavior of your XSLT here is not what you describe in the XML comments, or what I think you intended. `xml/*` has a higher template priority than `foo`, so what actually happens is that the third template is called three times and the second template isn't called at all. – JLRishe Apr 07 '13 at 22:37
  • @JLRishe Oh damn, this has been wrong all this time. Of course Ben is correct, I'll fix it immediately. Thanks for pointing this out! – Tomalak Apr 08 '13 at 04:38
  • 1
    > A concept to understand with XSLT is that of the "current node". With the current node moves on with every iteration, whereas does not change the current node. I.e. the . within a called template refers to the same node as the . in the calling template. This is not the case with apply-templates *** THANKS - This helped me a lot. – JanBorup Jun 17 '14 at 11:34
  • @Jan Nice to hear. That's one of the points easily missed by beginners, leading to complicated attempts to transfer context between different templates when in fact context is transferred automatically. – Tomalak Jun 17 '14 at 11:42
17

To add to the good answer by @Tomalak:

Here are some unmentioned and important differences:

  1. xsl:apply-templates is much richer and deeper than xsl:call-templates and even from xsl:for-each, simply because we don't know what code will be applied on the nodes of the selection -- in the general case this code will be different for different nodes of the node-list.

  2. The code that will be applied can be written way after the xsl:apply templates was written and by people that do not know the original author.

The FXSL library's implementation of higher-order functions (HOF) in XSLT wouldn't be possible if XSLT didn't have the <xsl:apply-templates> instruction.

Summary: Templates and the <xsl:apply-templates> instruction is how XSLT implements and deals with polymorphism.

Reference: See this whole thread: http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200411/msg00546.html

Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
11

xsl:apply-templates is usually (but not necessarily) used to process all or a subset of children of the current node with all applicable templates. This supports the recursiveness of XSLT application which is matching the (possible) recursiveness of the processed XML.

xsl:call-template on the other hand is much more like a normal function call. You execute exactly one (named) template, usually with one or more parameters.

So I use xsl:apply-templates if I want to intercept the processing of an interesting node and (usually) inject something into the output stream. A typical (simplified) example would be

<xsl:template match="foo">
  <bar>
    <xsl:apply-templates/>
  </bar>
</xsl:template>

whereas with xsl:call-template I typically solve problems like adding the text of some subnodes together, transforming select nodesets into text or other nodesets and the like - anything you would write a specialized, reusable function for.

Edit:

As an additional remark to your specific question text:

<xsl:call-template name="nodes"/> 

This calls a template which is named 'nodes':

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

This is a different semantic than:

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

...which applies all templates to all children of your current XML node whose name is 'nodes'.

Smandoli
  • 6,919
  • 3
  • 49
  • 83
TToni
  • 9,145
  • 1
  • 28
  • 42
2

The functionality is indeed similar (apart from the calling semantics, where call-template requires a name attribute and a corresponding names template).

However, the parser will not execute the same way.

From MSDN:

Unlike <xsl:apply-templates>, <xsl:call-template> does not change the current node or the current node-list.

Oded
  • 489,969
  • 99
  • 883
  • 1,009