Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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>
like image 646
Jakob Avatar asked Oct 25 '09 10:10

Jakob


People also ask

What does xsl apply templates select mean?

The <xsl:apply-templates> element applies a template to the current element or to the current element's child nodes. If we add a "select" attribute to the <xsl:apply-templates> element, it will process only the child elements that matches the value of the attribute.


1 Answers

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.

like image 61
Tim C Avatar answered Nov 24 '22 11:11

Tim C