XSL for Xml Schema Migration & Data Transformation

Ive recently been using XSL to do schema migration on XML data; ie small, incremental modifications to XML where most of the existing data is preserved. The application was to massage some Heroes of Arcadia level data, serialized with XStream, to keep in step with code changes I’d made.

First I tried using Scala’s scala.xml.transform.RewriteRule, but hit some bugs (#2124 and #2125) that convinced me to let it stabilize further before applied use.

So instead I used the new XSL support in Eclipse 3.5  (in WTP 3.1). Seems to work well.

I’d only used XSL back in 2001 and never fully understood it. I found most entry level tutorials (eg ZVON and W3 Schools) unhelpful for this kind of application, because they don’t explain copy existing nodes well.

My breakthrough came when I discovered Jesper Tverskov’s article on the Identity Template. This explains how to recursively process XML by copying with modification.

One case Jesper doesnt cover is copying where segments of the subtree are omitted and others are retained but modified.

I solved that in my template by using a <for-each> to pickout the subtree part I wanted to preserve, wrapping the <xsl:copy><xsl:apply-templates select=”@*|node()”/></xsl:copy> structure thats fundamental to recursive processing.

<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="//vector[default]">
<size><xsl:value-of select="default/elementCount"/></size>
<xsl:for-each select="default/elementData" >
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:for-each>
</xsl:template>

Sample input and output:

<__features id="50" serialization="custom">
<vector>
<default>
<capacityIncrement>4</capacityIncrement>
<elementCount>1</elementCount>
<elementData id="51">
<arcadia.domain.Unit reference="46"/>
<null/>
<null/>
<null/>
<null/>
</elementData>
</default>
</vector>
</__features>

<__features id="50" serialization="custom">
<size>1</size>
<elementData id="51">
<arcadia.domain.Unit reference="46"/>
<null/>
<null/>
<null/>
<null/>
</elementData>
</__features>

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: