xsltsymphony-cms

XSLT: Pass variable into template when using apply-templates


I'm not sure if this is asking too much of XSLT, but I'm after something similar to how mode works, except ideally within one template, rather than having to duplicate it as I am now:

<!-- Start -->
<xsl:apply-templates select="airports/airport" mode="start" />

<!-- End -->
<xsl:apply-templates select="airports/airport" mode="end" />

<!-- Template -->
<xsl:template match="airports/airport" mode="start">
    <option value="{@iata}" data-alternative-spellings="{.},{@iata}">
        <xsl:if test="@iata = 'LGW'">
            <xsl:attribute name="selected">selected</xsl:attribute>
        </xsl:if>
        <xsl:value-of select="@iata"/> - <xsl:value-of select="."/>
    </option>
</xsl:template>
<xsl:template match="airports/airport" mode="end">
    <option value="{@iata}" data-alternative-spellings="{.},{@iata}">
        <xsl:if test="@iata = 'LAX'">
            <xsl:attribute name="selected">selected</xsl:attribute>
        </xsl:if>
        <xsl:value-of select="@iata"/> - <xsl:value-of select="."/>
    </option>
</xsl:template>

The template applies the selected attribute if the value is something specific. This value needs to be different depending on what's calling the template. There are two cases, start and end that both have different criteria.

The easiest way to explain what I'm attempting to do is for me to write it in another language :)

<!-- Start -->
getAirports(start);

<!-- End -->
getAirports(end);

<!-- Template -->
var getAirports = function(position)
{
    var selected = '';
    switch(position)
    {
        case 'start':
            if(iata == 'LGW')
            {
                var selected = 'selected="selected"';
            }
        break;
        case 'end':
            if(iata == 'LAX')
            {
                var selected = 'selected="selected"';
            }
        break;
        default:
        break;
    }
    return '<option value="'+iata+'" data-alternative-spellings="'+iata+','+name+'" '+selected+'>'+iata+' - '+name+'</option>';
}

Is this possible in xslt, or will I have to stick to duplicating the template and using mode?

Thanks!


Solution

  • A fellow Twitter user gave me the solution, which can be found in this Gist.

    What I needed was with-param, something I've never used before:

    <!-- Start -->
    <xsl:apply-templates select="airports/airport">
        <xsl:with-param name="position" select="'start'" />
    </xsl:apply-templates>
    
    <!-- End -->
    <xsl:apply-templates select="airports/airport">
        <xsl:with-param name="position" select="'end'" />
    </xsl:apply-templates>
    
    <xsl:template match="airports/airport">
        <xsl:param name="position" />
        <option value="{@iata}" data-alternative-spellings="{.},{@iata}">
            <xsl:if test="(@iata = 'LGW' and $position = 'start') or (@iata = 'LAX' and $position = 'end')">
                <xsl:attribute name="selected">selected</xsl:attribute>
            </xsl:if>
            <xsl:value-of select="@iata"/> - <xsl:value-of select="." />
        </option>
    </xsl:template>