Deep copying with xsl:copy-of

Still talking about XSLT with Saxon, we have just see how to use xsl:copy, that we can think as a sort of shallow copy, now we'll see what about xsl:copy-of, that could be described as a deep element copy mechanism: we use it to copy a full element, its attributes and children included, from input to output.

An example of usage for xsl:copy-of could be this one. We have an XML with information about a buying order:

<?xml version="1.0" encoding="UTF-8"?>
<Order>
<From>ThisStuff</From>
<To>Buyer</To>
<DeliveryAddress>
<Street>Street</Street>
<City>City</City>
<State>State</State>
<ZipCode>12345</ZipCode>
<!-- more delivery information to be added -->
</DeliveryAddress>
<!-- other stuff here -->
</Order>

We want to generate another XML for the invoice. There the root element would be called Invoice, we want to swap From and To elements, and we want to keep unchanged the DeliveryAddress:

<?xml version="1.0" encoding="UTF-8"?>
<Invoice>
<From>Buyer</From>
<To>ThisStuff</To>
<DeliveryAddress>
<Street>Street</Street>
<City>City</City>
<State>State</State>
<ZipCode>12345</ZipCode>
<!-- more delivery information to be added -->
</DeliveryAddress>
<!--more invoice information to be added.-->
</Invoice>

To get such a result, we could use this transformation:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="/">
<Invoice>
<xsl:apply-templates select="/Order/To" />
<xsl:apply-templates select="/Order/From" />
<xsl:apply-templates select="/Order/DeliveryAddress" />
<xsl:comment>more invoice information to be added.</xsl:comment> <!-- 1 -->
</Invoice>
</xsl:template>

<xsl:template match="To">
<xsl:element name="From">
<xsl:value-of select="."/> <!-- 2 -->
</xsl:element>
</xsl:template>

<xsl:template match="From">
<xsl:element name="To">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>

<xsl:template match="DeliveryAddress">
<xsl:copy-of select="."/> <!-- 3 -->
</xsl:template>

</xsl:stylesheet>

1. That's how we insert a comment in the output XML, using the xsl:comment element.
2. A select on "." (dot) returns the current element.
3. Here we are using copy-of, so the complete element in input is copied to the output XML. Notice that even the comment is copied.

More information on XSLT and Saxon in chapter eight of Beginning XML by David Hunter et al. (Wrox).

No comments:

Post a Comment