Tintin81
Tintin81

Reputation: 10207

How to define attribute name dynamically in XSLT?

I have this XML:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl">

<xsl:param name="navigation-xml">
    <item id="home"         title-en="Services"     title-de="Leistungen" />
    <item id="company"      title-en="Company"      title-de="Unternehmen" />
    <item id="references"   title-en="References"   title-de="Referenzen" />
</xsl:param>

<xsl:param name="navigation" select="exsl:node-set($navigation-xml)/*" />
<xsl:param name="navigation-id" />

<xsl:template name="title">
    <xsl:apply-templates select="$navigation" mode="title" />
</xsl:template>

<xsl:template match="item" mode="title">
  <xsl:if test="$navigation-id = @id">
      <xsl:choose>
          <xsl:when test="$current-language = 'de'">
              <xsl:value-of select="@title-de" />
          </xsl:when>
          <xsl:otherwise>
              <xsl:value-of select="@title-en" />
          </xsl:otherwise>  
      </xsl:choose> 
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

How can I refactor the last 12 lines, so that the attribute name (either @title-de or @title-en) gets determined dynamically rather than in the (silly) way I did it in?

Thanks for any help.

Upvotes: 1

Views: 478

Answers (2)

michael.hor257k
michael.hor257k

Reputation: 116959

IMHO, your problem starts much earlier. If you define your navigation-xml parameter as:

<xsl:param name="navigation-xml">
    <item id="home">
        <title lang="en">Services</title>
        <title lang="de">Leistungen</title>
    </item> 
    <item id="company">
        <title lang="en">Company</title>
        <title lang="de">Unternehmen</title>
    </item> 
    <item id="references">
        <title lang="en">References</title>
        <title lang="de">Referenzen</title>
    </item> 
</xsl:param>

you will be able to address its individual nodes much more conveniently and elegantly.

Upvotes: 1

Martin Honnen
Martin Honnen

Reputation: 167426

You could write

<xsl:template name="title">
    <xsl:apply-templates select="$navigation" mode="title" />
</xsl:template>

<xsl:template match="item" mode="title">
  <xsl:if test="$navigation-id = @id">
      <xsl:choose>
          <xsl:when test="$current-language = 'de'">
              <xsl:value-of select="@title-de" />
          </xsl:when>
          <xsl:otherwise>
              <xsl:value-of select="@title-en" />
          </xsl:otherwise>  
      </xsl:choose> 
    </xsl:if>
</xsl:template>

as

<xsl:template name="title">
    <xsl:apply-templates select="$navigation[$navigation-id = @id]" mode="title" />
</xsl:template>

<xsl:template match="item" mode="title">
  <xsl:value-of select="@*[local-name() = concat('title-', $current-language)]" />
</xsl:template>

Upvotes: 2

Related Questions