XSLT <choose> Element

The XSLT <xsl:choose> element allows you to compare a value against a range of possible values in your XML document.

This element is used in conjunction with the <xsl:when> and (optionally) <xsl:otherwise> elements to present different content depending on the outcome of each test.

<xsl:choose> Example

The Source File

Imagine we have an XML file containing different food items and their nutritional value. Like this:

 
<?xml version="1.0"?>
<food_list>
  <food_item type="vegetable">
    <name>Agar</name>
    <carbs_per_serving>81</carbs_per_serving>
    <fiber_per_serving>8</fiber_per_serving>
    <fat_per_serving>0.5</fat_per_serving>
    <kj_per_serving>1280</kj_per_serving>
  </food_item>
  <food_item type="vegetable">
    <name>Asparagus</name>
    <carbs_per_serving>1</carbs_per_serving>
    <fiber_per_serving>1</fiber_per_serving>
    <fat_per_serving>0</fat_per_serving>
    <kj_per_serving>40</kj_per_serving>
  </food_item>
  <food_item type="vegetable">
    <name>Cabbage</name>
    <carbs_per_serving>0</carbs_per_serving>
    <fiber_per_serving>1</fiber_per_serving>
    <fat_per_serving>0</fat_per_serving>
    <kj_per_serving>14</kj_per_serving>
  </food_item>
  <food_item type="vegetable">
    <name>Potato</name>
    <carbs_per_serving>21.5</carbs_per_serving>
    <fiber_per_serving>2</fiber_per_serving>
    <fat_per_serving>1</fat_per_serving>
    <kj_per_serving>460</kj_per_serving>
  </food_item>
  <food_item type="vegetable">
    <name>Pumpkin</name>
    <carbs_per_serving>6</carbs_per_serving>
    <fiber_per_serving>1</fiber_per_serving>
    <fat_per_serving>0.5</fat_per_serving>
    <kj_per_serving>150</kj_per_serving>
  </food_item>
  <food_item type="vegetable">
    <name>Yam</name>
    <carbs_per_serving>30.5</carbs_per_serving>
    <fiber_per_serving>2</fiber_per_serving>
    <fat_per_serving>0.5</fat_per_serving>
    <kj_per_serving>550</kj_per_serving>
  </food_item>
  <food_item type="vegetable">
    <name>Zucchini</name>
    <carbs_per_serving>1.5</carbs_per_serving>
    <fiber_per_serving>1.5</fiber_per_serving>
    <fat_per_serving>0.5</fat_per_serving>
    <kj_per_serving>55</kj_per_serving>
  </food_item>
  <food_item type="seafood">
    <name>Abalone</name>
    <carbs_per_serving>0</carbs_per_serving>
    <fiber_per_serving>0</fiber_per_serving>
    <fat_per_serving>1</fat_per_serving>
    <kj_per_serving>400</kj_per_serving>
  </food_item>
  <food_item type="seafood">
    <name>Barramundi</name>
    <carbs_per_serving>0</carbs_per_serving>
    <fiber_per_serving>0</fiber_per_serving>
    <fat_per_serving>2</fat_per_serving>
    <kj_per_serving>390</kj_per_serving>
  </food_item>
  <food_item type="fruit">
    <name>Apple</name>
    <carbs_per_serving>15</carbs_per_serving>
    <fiber_per_serving>2.5</fiber_per_serving>
    <fat_per_serving>0</fat_per_serving>
    <kj_per_serving>250</kj_per_serving>
  </food_item>
  <food_item type="fruit">
    <name>Kiwi Fruit</name>
    <carbs_per_serving>7.5</carbs_per_serving>
    <fiber_per_serving>2.5</fiber_per_serving>
    <fat_per_serving>0</fat_per_serving>
    <kj_per_serving>150</kj_per_serving>
  </food_item>
  <food_item type="grain">
    <name>Oatbran</name>
    <carbs_per_serving>62</carbs_per_serving>
    <fiber_per_serving>14</fiber_per_serving>
    <fat_per_serving>7</fat_per_serving>
    <kj_per_serving>1400</kj_per_serving>
  </food_item>
  <food_item type="grain">
    <name>Wheatgerm</name>
    <carbs_per_serving>1.5</carbs_per_serving>
    <fiber_per_serving>1</fiber_per_serving>
    <fat_per_serving>0.5</fat_per_serving>
    <kj_per_serving>70</kj_per_serving>
  </food_item>
</food_list>

The Requirement

Now, imagine if we want to present the contents of our XML file in a table and highlight the rows a different color depending on the type of food it is. Something like this:

XML document formatted using the xslt 'choose' element

The Solution

We could do this using the following XSL file. In this file, we are checking the type attribute of the <food_item> element. We can find the value of the attribute by typing it's name with a @. If the value is grain we specify one color. If it's vegetable we specify another. If it's neither of these, we specify a default color using <xsl:otherwise>.

x
 
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <xsl:apply-templates/>
</xsl:template>
<xsl:template match="food_list">
  <table>
    <tr style="background-color:#ccff00">
      <th>Food Item</th>
      <th>Carbs (g)</th>
      <th>Fiber (g)</th>
      <th>Fat (g)</th>
      <th>Energy (kj)</th>
    </tr>
    <xsl:for-each select="food_item">
      <xsl:choose>
        <xsl:when test="@type = 'grain'">
          <tr style="background-color:#cccc00">
            <td><xsl:value-of select="name"/></td>
            <td><xsl:value-of select="carbs_per_serving"/></td>
            <td><xsl:value-of select="fiber_per_serving"/></td>
            <td><xsl:value-of select="fat_per_serving"/></td>
            <td><xsl:value-of select="kj_per_serving"/></td>
          </tr>
        </xsl:when>
        <xsl:when test="@type = 'vegetable'">
          <tr style="background-color:#00cc00">
            <td><xsl:value-of select="name"/></td>
            <td><xsl:value-of select="carbs_per_serving"/></td>
            <td><xsl:value-of select="fiber_per_serving"/></td>
            <td><xsl:value-of select="fat_per_serving"/></td>
            <td><xsl:value-of select="kj_per_serving"/></td>
          </tr>
        </xsl:when>
        <xsl:otherwise>
          <tr style="background-color:#cccccc">
            <td><xsl:value-of select="name"/></td>
            <td><xsl:value-of select="carbs_per_serving"/></td>
            <td><xsl:value-of select="fiber_per_serving"/></td>
            <td><xsl:value-of select="fat_per_serving"/></td>
            <td><xsl:value-of select="kj_per_serving"/></td>
          </tr>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </table>
</xsl:template>
</xsl:stylesheet>