tags:

views:

314

answers:

3

I know that XSLT does not work in procedural terms, but unfortunately I have been doing procedural languages for too long. Can anyone help me out by explaining in simple terms how things like apply-templates works and help a thicko like me to understand it.

+5  A: 

I wrote a blog entry ages ago that shows a simple stylesheet written in a 'procedural' style using xsl:for-each and the equivalent using xsl:apply-templates. It's by no means a comprehensive guide but hopefully it will be of some use.

Greg Beech
I'm not sure I agree with the sentiment - for-each structures are *much* easier for !XSLT guys to understand and XSLT is seen as voodoo by too many already (readability counts) - but it's a well written piece
annakata
This does start to diminish the mysticism surrounding the magical apply-templates for me. Also, I have just found that stepping through examples using Visual Studio (2008) has helped too.
Xetius
Fully agree with the blog post. For more details on this subject, see my answer.
Dimitre Novatchev
+4  A: 

What makes you think that procedural terms do not apply here? It's just that the calling convention is somewhat more implicit than you would traditionally expect it, because there is an invisible context involved. Everything apply-templates does could be expressed in procedural terms.

Basically, apply-templates is nothing more than a for-each loop. Starting from where where you currently are in the document (the context, think "this"), it iterates over the child nodes.

For each child, the processor selects the matching xsl:template with the highest priority (based on their respective match and priority attributes), sets the context to the child at hand and runs this template (think "function"). After the template returns, the context snaps back and it's the next child's turn.

Even when things become recursive (which is somewhat hard to avoid in XSLT), the whole process really does not become any more complicated. The context "pointer" is moved around, and templates get called.

You can restrict the node set that apply-templates iterates over, using the select attribute:

<!-- all children of the context node regardless -->
<xsl:apply-templates />  

<!-- all children of the context node being "data" with a @name of "Foo" -->
<xsl:apply-templates select="data[@name='Foo']" />  

You can sort the node-set prior to the iteration, if you wish:

<!-- all children of the context node being "data" with a @name of "Foo",
     ordered by their respective "detail" count -->
<xsl:apply-templates select="data[@name='Foo']"> 
  <xsl:sort select="count(detail)" data-type="number" order="descending"/>
</xsl:apply-templates>

And you can pass parameters to your template if you need, just like you would with a regular function call:

<!-- pass in some parameter -->
<xsl:apply-templates select="data[@name='Foo']"> 
  <xsl:with-param name="DateSetIcon" select="$img_src" />
</xsl:apply-templates>

That's about all there is to it.

EDIT:

I know that the last comment is a bit provocative. This is very much intentional, for a basic understanding of how apply-templates works this is more or less it. The implications and possibilities that come from the fact that not you are defining what template to call, but rather let the processor choose the right one for you are of course bigger than what it sounds like to the untrained ear. The declarative/implicit approach of the whole thing surely needs some time to sink in.

Tomalak
"That's about all there is to it"... Not exactly, see my answer.
Dimitre Novatchev
+2  A: 
Dimitre Novatchev
I don't see what would be incorrect in my answer. You add details on execution order, but for the transformation result (and anything else, XSL should be side-effect free) execution order is irrelevant, or is it not? My "about that's all there is" maybe provocative, but what else is there?
Tomalak
Tomalak, my comment was: ""That's about all there is to it"... Not exactly, see my answer". I didn't ever say your answer was incorrect. Simply, <xsl:apply-templates> is a much bigger topic. Cheers
Dimitre Novatchev
I imagined that "not exactly" would be a friendlier way of saying "that's wrong" (it usually is in the English-speaking world).
Tomalak
(And, putting two and two together, I thought that the down-vote was yours and that there must be an error in my answer.)
Tomalak
Hey, I haven't downvoted for a long time! :) Thanks for reminding me. And no, I didn't even know (no way to see it) that your answer was downvoted. Do you want to verify this? I can send you a screenshot of my "Votes" tab. Cheers
Dimitre Novatchev
Not necessary, I believe you! ;-) It's no big deal anyway. Sometimes down-votes can be aligned to "I don't think so" comments, so it just seemed likely. It's too bad that down-votes often come with no explanation.
Tomalak
Yes, I think it would be good if SO changes the way of downvoting by making an explanation mandatory. Maybe even show the userid of the downvoter.
Dimitre Novatchev
This would only work if every user was sensible and fair, which can safely be ruled out. Many users would switch to an "an eye for an eye" mode... Unfortunately nobody can seem to think of a workable alternative, various suggestions on Uservoice have been made, but all were flawed some way or other.
Tomalak