How do I apply templates to each selected node in a for-each?

apply-templates, foreach, xslt

Solution

I would agree with 'ndim' that you should probably restructure your XSLT to do away with the xsl:for-each loop.

Alternatively, you could amend the xsl:apply-templates to select the current track node within the xsl:for-each

<xsl:for-each select="track">
   <li>
      <xsl:apply-templates select="." />
   </li>
</xsl:for-each>

Keeping the xsl:for-each would, at least, allow you to sort the tracks in another order, if desired.

Problem

I know I'm missing something here. In the XSLT transformation below, the actual result doesn't match the desired result. Inside the `for-each`, I want to apply the `match="track"` template to each selected `track` element. If I've understood XSLT properly, with the current setup only child nodes of each selected `track` element are matched against templates, not the `track` elements themselves. How can I make the `track` elements go through the template as desired? Do I need to rethink my entire approach? Note: The transformation is executed using PHP. XML declarations have been omitted for brevity. XML Document: ``` <album> <title>Grave Dancers Union</title> <track id="shove">Somebody To Shove</track> <track id="gold">Black Gold</track> <track id="train">Runaway Train</track> <producer>Michael Beinhorn</producer> </album> ``` XSL Stylesheet: ``` <xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/album"> <ol> <xsl:for-each select="track"> <li><xsl:apply-templates/></li> </xsl:for-each> </ol> </xsl:template> <xsl:template match="track"> <a href="{@id}"><xsl:apply-templates/></a> </xsl:template> </xsl:stylesheet> ``` Result: ``` <ol> <li>Somebody To Shove</li> <li>Black Gold</li> <li>Runaway Train</li> </ol> ``` Desired Result: ``` <ol> <li><a href="shove">Somebody To Shove</a></li> <li><a href="gold">Black Gold</a></li> <li><a href="train">Runaway Train</a></li> </ol> ```

Original source