Translating Between Schemas
A version of this page is also available for
4/8/2010
An XSLT style sheet can translate data from one XML grammar to another. The mechanisms in XSLT can be applied directly to any XML grammar. Templates can be created using elements from the output grammar and populated using <xsl:for-each>, <xsl:value-of>, and so on.
Imagine that you receive stock quotes in the format shown in the following code example.
<?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 the rest of your stock information, which uses a different schema. You would like this information to look like this.
<?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>
To transform the investments data into the portfolio grammar, you can use familiar XSLT techniques. Your templates will contain output elements such as stock instead of HTML elements. Attribute values are extracted using <xsl:value-of> and either generate new attributes using <xsl:attribute> or are converted to elements.
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="https://www.w3.org/1999/XSL/Transform" version="1.0">
<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>
This example also shows XSLT generating a document that declares a namespace. The data types namespace declaration on the <portfolio> element is treated by XSLT like any other attribute appearing on an output element and passed through. In this case, the XSLT namespace declaration is passed through as well.
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 xmlns:xsl="https://www.w3.org/1999/XSL/Transform" version="1.0">
<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 the use of <xsl:attribute> to not only copy an attribute value to a new attribute, but also to convert element content to attribute values.