The reason you're getting two ul
elements is because your template that generates the ul
element matches elements called WideTeaserElement
, of which you have two.
I think I can see where thinking was going with this- were you assuming that this template would process all WideTeaserElement
s in one operation, which you could then iterate through with 'for each of these'? Instead, the template is called separately for each occurrence of the WideTeaserElement
node, and then 'iterates' through the single occurrence of itself.
I agree with Norman that for-each
is rarely the best option, but I can think of two reasons why you might use it.
- Readability; if the amount of processing for each iteration is relatively small, it can make your stylesheet easier to read if it the code that handles it is within the parent template.
For (very simplified) example, I'd favor
<xsl:template match="mylist">
<xsl:element name="ul">
<xsl:for-each select="listitem">
<xsl:element name="li">
<xsl:value-of select="." />
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
instead of
<xsl:template match="mylist">
<xsl:element name="ul">
<xsl:apply-templates select="listitem" />
</xsl:element>
</xsl:template>
<xsl:template match="listitem">
<xsl:element name="li">
<xsl:value-of select="." />
</xsl:element>
</xsl:template>
if the mylist
template actually had a lot more code, and the latter solution would mean having to scroll down my code to see how listitem
is handled. This is subjective though, some may prefer the latter solution always. Personally I usually find that most templates are large enough that breaking them up is better for readability, but in smaller ones this isn't always the case.
- Where you don't want the nodes your iterating through to be treated as they normally would by a template. In the above example, the latter solution would convert ALL
listitem
tags, not just those within a 'mylist' tag. It's possible to restrict it by changing the match to listitem[parent::mylist]
of course, but often the for-each
is just neater than making multiple templates for the same element name based on ancestry.
Generally speaking though, you can usually substitute
<xsl:template match="foo">
<xsl:for-each select="bar">
..
</xsl:for-each>
</xsl:template>
with
<xsl:template match="foo">
<xsl:apply-templates select="bar" />
</xsl:template>
<xsl:template match="bar">
..
</xsl:template>
in any document where a bar
element always has a foo
element as it's parent.