Microsoft XML 2.5 SDK


 

Conditional Templates

[This is preliminary documentation and subject to change.]

Conditional templates are output only if certain conditions exist within the source document. XSL defines conditional templates with the <xsl:if> and <xsl:choose> elements.

Notice in the following portfolio data that the "stock" element has an attribute named "exchange". You might want to generate some output only when this attribute has a certain value.

<?xml version="1.0"?>
<portfolio xmlns:dt="urn:schemas-microsoft-com:datatypes">
  <stock exchange="nyse">
    <name>zacx corp</name>
    <symbol>ZCXM</symbol>
    <price dt:dt="number">28.875</price>
  </stock>
  <stock exchange="nasdaq">
    <name>zaffymat inc</name>
    <symbol>ZFFX</symbol>
    <price dt:dt="number">92.250</price>
  </stock>
  <stock exchange="nasdaq">
    <name>zysmergy inc</name>
    <symbol>ZYSZ</symbol>
    <price dt:dt="number">20.313</price>
  </stock>
</portfolio>

You could easily create another row in the table in which to place the attribute value. But suppose you want to indicate stocks from a particular exchange not by a completely new table row, but by noting them with an "*". The <xsl:if> element provides a mechanism for conditionally inserting structure into the output tree.

In the following example, the <xsl:if> element inserts an "*" after the symbol for those stocks listed on the NASDAQ stock exchange. The <xsl:if> contents can be simple text, as in this example, or elements, attributes—any structure allowed by XSL.

<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
  <xsl:template match="/">
    <HTML>
      <BODY>
        <TABLE BORDER="2">
          <TR>
            <TD>Symbol</TD>
            <TD>Name</TD>
            <TD>Price</TD>
          </TR>
          <xsl:for-each select="portfolio/stock">
            <TR>
              <TD>
                <xsl:value-of select="symbol"/>
                <xsl:if test="@exchange[.='nasdaq']">*</xsl:if>
              </TD>
              <TD><xsl:value-of select="name"/></TD>
              <TD><xsl:value-of select="price"/></TD>
            </TR>
          </xsl:for-each>
        </TABLE>
        <P>* Listed on Nasdaq stock exchange</P>
      </BODY>
    </HTML>
  </xsl:template>
</xsl:stylesheet>

The test attribute takes an XSL pattern. If the query described by the pattern selects one or more nodes, the <xsl:if> template is inserted. If the selection is empty, the conditional is skipped. In this case, the query checks to see if the stock element has an "exchange" attribute, and further checks that the value of the exchange attribute is equal to "nasdaq". For more information on qualifying a pattern using brackets ([]) and constructing patterns that compare values, see XSL Patterns.

Choosing Alternatives

The <xsl:choose> element provides a mechanism for "either/or" processing. <xsl:choose> contains a series of <xsl:when> elements that are tested in order from top to bottom until a match is found. An <xsl:otherwise> element can be used to insert a template if no match is found.

The following could be added to the above example to color-code the rows by price—0-25 are displayed in green, 25-50 are displayed in blue, and 50+ are displayed in red. The color is changed by conditionally generating a portion of the value of the STYLE attribute on the table row.

<TR>
  <xsl:attribute name="STYLE">color:
    <xsl:choose>
      <xsl:when test="price[. $le$ 25]">green</xsl:when>
      <xsl:when test="price[. $le$ 50]">blue</xsl:when>
      <xsl:otherwise>red</xsl:otherwise>
    </xsl:choose>
  </xsl:attribute>
  <TD>
    ...

The $le$ operator (less-than-or-equals) is an XSL Pattern extension described in the XQL Proposal, and is not part of the December 1998 XSL Working Draft.