Translating from One XML Schema to Another

MSXML 5.0 SDK

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

Translating from One XML Schema to Another

An XSLT style sheet can be applied to translate data from one XML grammar to another. Suppose that you receive stock quotes marked up in the following format:

<?xml version="1.0"?>
<investments>
  <item type="stock" exch="nyse"   symbol="ZCXM" company="zacx corp"
        price="28.875"/>
  <item type="stock" exch="nasdaq" symbol="ZFFX" company="zaffymat inc"
        price="92.250"/>
  <item type="stock" exch="nasdaq" symbol="ZYSZ" company="zysmergy inc"
        price="20.313"/>
</investments>

You want to add this information to your portfolio of the following format.

<?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>

This amounts to translating from one XML schema to another. You can use XSLT to transform the <investments> data into the <portfolio> grammar. When you do this, your templates will contain output elements such as <stock>, instead of HTML elements. The following XSLT style sheet is an example.

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
  <portfolio xmlns:dt="urn:schemas-microsoft-com:datatypes">
    <xsl:for-each select="investments/item[@type='stock']">
      <stock>
        <xsl:attribute name="exchange">
            <xsl:value-of select="@exch"/>
        </xsl:attribute>
        <name><xsl:value-of select="@company"/></name>
        <symbol><xsl:value-of select="@symbol"/></symbol>
        <price dt:dt="number"><xsl:value-of select="@price"/></price>
      </stock>
    </xsl:for-each>
  </portfolio>
</xsl:template>

</xsl:stylesheet>

Notice that in the resulting document, the <portfolio> element generated by this XSLT also declares a namespace for data types used to scope the dt attribute in the enclosing <price> element. The dt namespace prefix that precedes the dt attribute (dt:dt="number") indicates that the number type is defined in urn:schemas-microsoft-com:datatypes.

The translation can be performed in reverse with a similar style sheet, converting <portfolio> data to the <investments> grammar.

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
  <investments>
    <xsl:for-each select="portfolio/stock">
      <item type="stock">
        <xsl:attribute name="exch"><xsl:value-of select="@exchange"/></xsl:attribute>
        <xsl:attribute name="symbol"><xsl:value-of select="symbol"/></xsl:attribute>
        <xsl:attribute name="company"><xsl:value-of select="name"/></xsl:attribute>
        <xsl:attribute name="price"><xsl:value-of select="price"/></xsl:attribute>
      </item>
    </xsl:for-each>
  </investments>
</xsl:template>

</xsl:stylesheet>

Note that <xsl:attribute> is used not only to copy an attribute value to a new attribute, but also to convert element content to attribute values.