Templates¶
XSLT is at heart a rule-based, declarative language. Instead of one big
procedure, you write many small xsl:template rules — each says "when you see
this kind of node, produce that output" — and let the processor decide which
rule applies where.
apply-templates¶
The engine is xsl:apply-templates. It tells the processor: "find the matching
template for each selected node and run it." Compare this version with the
single-template one from the previous page:
- The root template lays out the page, then delegates with a bare
xsl:apply-templates— process all my children. - A template for
cdelements. It only cares about laying out one CD, and delegates the actual fields to their templates. - A template for
title.select="."means "the current node" — here, thetitleelement whose text we want.
Each rule has one job. There is one important qualification: this particular
cd template delegates only to title and artist. Adding a <year> rule
alone would therefore not make the year appear, because no instruction reaches
the year node. You would either add
<xsl:apply-templates select="year"/> to the cd template, or deliberately
switch it to a bare <xsl:apply-templates/> so every child is offered to the
template rules. Once a node is part of that walk, changing how it renders means
editing its small template rather than a monolith.
How a node is matched¶
xsl:apply-templates selects a set of nodes (its children by default, or
whatever select names). For each node, the processor picks the best-matching
template by its match pattern. The patterns above (cd, title, artist)
use XPath-like syntax, but a match pattern is not an ordinary XPath expression.
An XPath select starts at a context node and navigates to a result; a match
pattern works in the other direction conceptually, asking whether the candidate
node has the required name, ancestry, or other pattern properties. The pattern
cd, for example, matches a candidate cd element wherever the processing
walk reaches one; it does not select a cd child relative to some other node.
A template only fires when it is reached¶
This is the single most common gap for newcomers, so it is worth stating plainly:
Defining a template does not run it
A xsl:template is a dormant rule. It produces output only when some
xsl:apply-templates reaches a node it matches — never just because it
exists in the stylesheet.
In the example above, the title template fires for one reason only: the cd
template explicitly pushes the node to it with <xsl:apply-templates
select="title"/>. Delete that line and the title template never runs — its
red <span> simply never appears in the output, even though the rule is still
sitting there.
\"Children\" means children in the source document
xsl:apply-templates always works on the document being transformed,
relative to the current node — never on the layout of the stylesheet.
The templates sit side by side as top-level rules; none is nested inside
another. When the cd template runs, the current node is a <cd> element
in the source XML, and its children are the source elements <title>,
<artist>, <price> (plus the whitespace text between them). The push model
walks the data tree; match patterns decide which rule catches each
node. The physical nesting of templates in the .xsl file is irrelevant.
Two things follow from this that often trip people up:
-
It is not the
select="title"that matters — it is the reach. A bare<xsl:apply-templates/>in thecdtemplate would also fire thetitletemplate, because the bare form processes every child of the current<cd>source element, and the<title>element is one of them (so is<artist>, plus the built-in rule for the text nodes).select="title"just narrows which of those children get processed; it does not "call" the template by name. -
The chain has to actually arrive at the node. Processing flows root →
apply-templates→cd→apply-templates→title. Break the chain at any link above and thetitletemplate becomes unreachable, no matter how well itsmatchpattern fits.
This is the difference between pull and push. The single big template on
the first page pulls: <xsl:value-of
select="title"/> goes and fetches the text where it is written. Here the cd
template pushes: apply-templates hands the title node to whichever rule
matches it. No push, no match — no output.
What the two select calls actually control¶
Splitting the work into two sequential instructions —
— does two distinct things, and it is worth separating them.
Order. The result order follows the order of the instructions, not the
source document. You get title-then-artist because that is the order the two
lines are written, even if the source had <artist> first. A bare
<xsl:apply-templates/>, by contrast, processes children in document order,
so the output would mirror the source. (Within a single select, order is
always document order — sequencing separate instructions is what lets you
override it, short of xsl:sort.)
Filtering. <cd> also has a <price> child. With explicit
select="title" / select="artist", the <price> node is never reached, so it
is omitted. A bare <xsl:apply-templates/> would reach it, and since there is
no price template, the built-in rule would dump its text (10.90) into the
output.
In this example, the filtering matters more than the order
The source catalog.xml already lists <title> before <artist>, so a
bare apply-templates would produce the same order here. The explicit
selects earn their keep by excluding <price> — and by guaranteeing the
order regardless of how the source happens to be arranged.
The built-in templates¶
You never wrote a template for the text inside title, yet the text appeared.
That is because XSLT ships built-in templates:
- For any element with no matching rule: recurse into its children
(
apply-templates). - For text and attribute nodes: copy their value to the output.
This is why a stylesheet with no templates at all still emits all the text content of a document. It is convenient, but also a common surprise — stray text in the output usually means a node fell through to the built-in rule.
select vs match
They look similar but do different jobs. match (on xsl:template) is a
pattern that decides whether a rule applies. select (on
apply-templates, value-of, for-each) is an expression that chooses
which nodes to act on.
Two styles, one result¶
You now have two ways to walk a document:
| Style | Drives iteration | Best when |
|---|---|---|
xsl:for-each |
You, explicitly | The structure is simple and regular |
xsl:apply-templates |
The processor, by matching | Content is mixed, recursive, or reused |
Match templates handle "for every node of this kind." When you instead need a direct loop and explicit text output, continue with loops and output. Named templates come later, after variables and conditionals, when their parameters and recursive structure have more familiar foundations.