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.
views:
314answers:
3I 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.
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.