Arcadia’s level editor lives again

This is a sight I havent seen for 3 months – my game’s level editor working. Its a relief to have it back (partially).

Heavy refactoring of game code, technical debt and experimentation have conspired to make it broken. Its taken much of the past month to fix.

Resource_-_ArcadiaResourcesScenariosNuWoodhaven.scenario.xml_-_Eclipse_SDK-2009.07.06-19.03.27

Advertisements

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>