Microsoft XML Core Services (MSXML) 5.0 for Microsoft Office - XSLT Developer's Guide

Step 2: Creating the New Element

Step 2 adds code to the second template rule described in Step 1: Cloning the Source Tree—that is, the rule fired as a result of the mode="calc_usd" attribute. The new code creates a new child for each <product> element. This new child, <usd_equiv>, contains the US dollars equivalent of the product's price in local currency. The prodsortcvar2.xsl example, below, shows this template rule, with changes in bold.

Note   The element created by the <xsl:element> here could also have been created as a literal result element. That is, the <xsl:element name="usd_equiv"> start tag could be replaced with <usd_equiv>, and the </xsl:element> end tag could be replaced with </usd_equiv>.

The changes below create a variable, prods_with_usd. This variable contains a result tree fragment consisting of each product's data (copied from the source tree), and a new element for each product, <usd_equiv>. All that's left is to apply the sort to this slightly altered source tree clone, and place its results in table rows (one per product).

XML File (prodsort.xml)

Use prodsort.xml, in Sample XML Data File for XSLT Sorting. Change the href attribute to reference prodsortcvar2.xsl.

XSLT File (prodsortcvar2.xsl)

<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
   <HTML>
      <HEAD>
         <TITLE>Wooden Rings and More!</TITLE>
         <STYLE type="text/css">
            th {background-color: silver;
               font-family: Tahoma,Verdana,Arial,sans-serif}
            td {background-color: white;
               font-family: Tahoma,Verdana,Arial,sans-serif}
         </STYLE>
      </HEAD>
      <BODY>
         <xsl:apply-templates/>
      </BODY>
   </HTML>
</xsl:template>

<xsl:template match="products">
    <!-- Create a variable to hold the generated result tree fragment. -->
    <xsl:variable name="prods_with_usd">
        <xsl:apply-templates select="product" mode="calc_usd" />
    </xsl:variable>
    <TABLE width="75%">
        <tr>
            <th>Category</th>
            <th>Prod ID</th>
            <th>Name/Version</th>
            <th>Description</th>
            <th>Price (Currency)</th>
            <th>Price (USD)</th>
        </tr>
    </TABLE>
</xsl:template>

<xsl:template match="product" mode="calc_usd">
    <xsl:copy>
        <xsl:copy-of select="@*" />
        <xsl:copy-of select="*" />
        <!-- Add a calculated <usd_equiv> child to each <product>. -->
        <xsl:element name="usd_equiv">
            <xsl:choose>
                <!-- Note: Exchange rates current as of Oct. 2000 -->
                <xsl:when test="price/@curr='USD'">
                    <xsl:value-of select="format-number(price, '#,##0.00')"/>
                </xsl:when>
                <xsl:when test="price/@curr='GBP'">
                    <xsl:value-of select="format-number(price * 1.47275, '#,##0.00')"/>
                </xsl:when>
                <xsl:when test="price/@curr='EU'">
                    <xsl:value-of select="format-number(price * 0.864379, '#,##0.00')"/>
                </xsl:when>
                <xsl:otherwise>Unknown Currency</xsl:otherwise>
            </xsl:choose>
        </xsl:element>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>