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?
apply-templatesxslt
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?
As with all performance questions, the answer will depend on your particular configuration (in particular the XSLT processor you're using) and the kind of processing that you're doing.
<xsl:apply-templates>
takes a sequence of nodes and goes through them one by one. For each, it locates the template with the highest priority that matches the node, and invokes it. So <xsl:apply-templates>
is like a <xsl:for-each>
with an <xsl:choose>
inside, but more modular.
In contrast, <xsl:call-template>
invokes a template by name. There's no change to the context node (no <xsl:for-each>
) and no choice about which template to use.
So with exactly the same circumstances, you might imagine that <xsl:call-template>
will be faster because it's doing less work. But if you're in a situation where either <xsl:apply-templates>
or <xsl:call-template>
could be used, you're probably going to be doing the <xsl:for-each>
and <xsl:choose>
yourself, in XSLT, rather than the processor doing it for you, behind the scenes. So in the end my guess it that it will probably balance out. But as I say it depends a lot on the kind of optimisation your processor has put into place and exactly what processing you're doing. Measure it and see.
My rules of thumb about when to use matching templates and when to use named templates are:
<xsl:apply-templates>
and matching templates if you're processing individual nodes to create a result; use modes if a particular node needs to be processed in several different ways (such as in the table of contents vs the body of a document)<xsl:call-template>
and a named template if you're processing something other than an individual node, such as strings or numbers or sets of nodes<xsl:function>
if you're returning an atomic value or an existing nodeI love your question. You're very articulate about what you do not yet understand. You just need something to tie things together. My recommendation is that you read "How XSLT Works", a chapter I wrote to address exactly the questions you're asking. I'd love to hear if it ties things together for you.
Less formally, I'll take a stab at answering each of your questions.
- In what order do the templates execute, and
- When they execute, do they match on (a) the original source XML, or (b) the current output of the XSLT to that point?
At any given point in XSLT processing, there are, in a sense, two contexts, which you identify as (a) and (b): where you are in the source tree, and where you are in the result tree. Where you are in the source tree is called the current node. It can change and jump all around the source tree, as you choose arbitrary sets of nodes to process using XPath. However, conceptually, you never "jump around" the result tree in the same way. The XSLT processor constructs it in an orderly fashion; first it creates the root node of the result tree; then it adds children, building the result in document order (depth-first). [Your post motivates me to pick up my software visualization for XSLT experiments again...]
The order of template rules in a stylesheet never matters. You can't tell, just by looking at the stylesheet, in what order the template rules will be instantiated, how many times a rule will be instantiated, or even whether it will be at all. (match="/"
is an exception; you can always know that it will get triggered.)
I am assuming that Template #1 will execute first. I don't know why I assume this -- is it just because it appears first in the document?
Nope. It would be called first even if you put it last in the document. Template rule order never matters (except under an error condition when you have more than one template rule with the same priority matching the same node; even then, it's optional for the implementor and you should never rely on such behavior). It gets called first because the first thing that always happens whenever you run an XSLT processor is a virtual call to <xsl:apply-templates select="/"/>
. The one virtual call constructs the entire result tree. Nothing happens outside it. You get to customize, or "configure", the behavior of that instruction by defining template rules.
Will Template #2 execute? It matches a node in the source XML, but by the time the we get to this template (assuming it runs second), the "firstName" node will not be in the output tree.
Template #2 (nor any other template rules) will never get triggered unless you have an <xsl:apply-templates/>
call somewhere in the match="/"
rule. If you don't have any, then no template rules other than match="/"
will get triggered. Think of it this way: for a template rule to get triggered, it can't just match a node in the input. It has to match a node that you elect to process (using <xsl:apply-templates/>
). Conversely, it will continue to match the node as many times as you choose to process it.
Would [the
match="/"
template] pre-empt all other templates from executing since there is nothing to match on after that first template is complete?
That rule preempts the rest by nowhere including <xsl:apply-templates/>
in it. There are still plenty of nodes that could be processed in the source tree. They're always all there, ripe for the picking; process each one as many times as you want. But the only way to process them using template rules is to call <xsl:apply-templates/>
.
To this point, I've been concerned with later templates not executing because the nodes they have operated on do not appear in the output, but what about the inverse? Can an "earlier" template create a node that a "later" template can do something with?
It's not that an "earlier" template creates a new node to be processed; it's that an "earlier" template in turn processes more nodes from the source tree, using that same instruction (<xsl:apply-templates
). You can think of it as calling the same "function" recursively, with different parameters each time (the nodes to process as determined by the context and the select
attribute).
In the end, what you get is a tree-structured stack of recursive calls to the same "function" (<xsl:apply-templates>
). And this tree structure is isomorphic to your actual result. Not everyone realizes this or has thought about it this way; that's because we don't have any effective visualization tools...yet.
Template #1 creates a new node called "fullName". Template #2 matches on that same node. Will Template #2 execute because the "fullName" node exists in the output by the time we get around to Template #2?
Nope. The only way to do a chain of processing is to explicitly set it up that way. Create a variable, e.g., $tempTree
, that contains the new <fullName>
element and then process it, like this <xsl:apply-templates select="$tempTree">
. To do this in XSLT 1.0, you need to wrap the variable reference with an extension function (e.g., exsl:node-set()
), but in XSLT 2.0 it will work just as is.
Whether you're processing nodes from the original source tree or in a temporary tree that you construct, either way you need to explicitly say what nodes you want to process.
What we haven't covered is how XSLT gets all its implicit behavior. You must also understand the built-in template rules. I write stylesheets all the time that don't even include an explicit rule for the root node (match="/"
). Instead, I rely on the built-in rule for root nodes (apply templates to children), which is the same as the built-in rule for element nodes. Thus I can ignore large parts of the input, let the XSLT processor automatically traverse it, and only when it comes across a node I'm interested in will I do something special. Or I could write a single rule that copies everything recursively (called the identity transform), overriding it only where necessary, to make incremental changes to the input. After you've read "How XSLT Works", your next assignment is to look up the "identity transform".
I realize that I'm deeply ignorant about the "zen" of XSLT. To date, my stylesheets have consisted of a template matching the root node, then are completely procedural from there. I'm tired of doing this. I would rather actually understand XSLT correctly, hence my question.
I applaud you. Now it's time to take the "red pill": read "How XSLT Works"
Best Solution
<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.
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 theselect
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: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
andpriority
, the fact that templates can have both aname
and amatch
. 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.