<xsl:for-each>
The last of the control flow elements, <xsl:for-each>,
has already been seen in action when we were counting the number of scenes in
each act. Here is the stylesheet (count.xsl)
that we used:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template
match="PLAY">
<HTML>
<HEAD>
<TITLE>Counting</TITLE>
</HEAD>
<BODY>
<P>There are
<xsl:value-of
select="count(//PERSONA)"/> individual
characters in
Hamlet.</P>
<P>
<xsl:for-each
select="ACT">
<xsl:value-of
select="TITLE"/> has
<xsl:value-of
select="count(SCENE)"/>
scenes,
</xsl:for-each>
making a total of
<xsl:value-of
select="count(//SCENE)"/>.
</P>
</BODY>
</HTML>
</xsl:template>
</xsl:stylesheet>
The <xsl:for-each>
statement
effectively allows us to embed a template inside another. Instead of the <xsl:for-each>
statement, we could have used <xsl:apply-templates>,
and made
the contents of the <xsl:for-each> a separate template:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template
match="PLAY">
<HTML>
<HEAD>
<TITLE>Counting</TITLE>
</HEAD>
<BODY>
<P>There are
<xsl:value-of
select="count(//PERSONA)"/> individual
characters in
Hamlet.</P>
<P>
<xsl:apply-templates
select="ACT"/>
making a total of
<xsl:value-of
select="count(//SCENE)"/>.
</P>
</BODY>
</HTML>
</xsl:template>
<xsl:template
match="ACT">
<xsl:value-of
select="TITLE"/> has
<xsl:value-of
select="count(SCENE)"/> scenes,
</xsl:template>
</xsl:stylesheet>
So when should you use <xsl:for-each>
and when should
you use <xsl:apply-templates>?
Often, the same template will be executed as a result of several XPath
expression matches. In this case, using <xsl:apply-templates>
provides
re-usability in the same way that a function call does in a procedural
language. On other occasions, it is largely a matter of style, and you should
use whichever makes your stylesheet easier to understand. As we saw earlier, a
push model stylesheet tends to use <xsl:apply-templates>
most of
the time to execute specific template rules as elements are found in the source
tree, while a pull model is more likely to have a single large template with <xsl:for-each>
statements to execute the embedded rule at a specific point in the stylesheet.
XSLT has the concept of a context
node, which is important when using relative XPath expressions. In the
stylesheet above, the line:
<xsl:template match="ACT">
sets the context node to the <ACT>
element. In the following line:
<xsl:value-of select="TITLE"/> has
the expression is relative
to this context node. There are two ways of changing the context node
in XSLT: <xsl:template> is one, and <xsl:for-each> is
the other. These are the only ways of changing the context node. Using an XPath
expression in a test attribute, for example, does not do this.