Saturday, July 28, 2007

How to REST?! - XML Transformation

In the previous sections, we sent and received XML messages to/from web service.In this communication the client and web service received the XML message in the formats that they were expecting. These formats were defined in the XML schema files. But sometimes we need to adapt ourselves with different formats of information. For example some services may use email instead of username to identify their customers. So we must provide a way for different XML formats to be acceptable by our RESTful web service.Here we need to transform the incoming xml message to an acceptable format. We can use XSLT for this reason.XSLT makes sense as the transformation tool of choice within SOA integration frameworks, because it is a universally accepted standard and the transformation engines that interpret XSLT to perform data transformations keep getting better and faster.

As an example assume that the authentication message came from the client is in the following format:
<?xml version="1.0"?>
<auth xmlns="http://www.javadev.org/mail" xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance" xsi:schemaLocation="http://www.javadev.org/mail
http://javadev.org/rest/auth/mail.xsd">
<email>foo</email>
<password>foo</password>
</auth>

As you can see <username> is replaced with <email> , for the authentication service there is no difference between username and email, because both of them are unique. But the main point of the consideration is that currently, when we are parsing the incoming xml document, we expect the <username> element but we are facing an <email> element.To transform the incoming XML document to the expected format we write an XSLT and use it in the JAXP API.The XSLT document is as bellow:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:mail=
http://www.javadev.org/mail>
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="mail:auth">
<auth xmlns="http://www.javadev.org/auth" xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xsi:schemaLocation="http://www.javadev.org/auth
http://javadev.org/rest/auth/auth.xsd">
<xsl:apply-templates/>
</auth>
</xsl:template>
<xsl:template match="mail:email">
<xsl:apply-templates select="./mail:email"/>
</xsl:template>
<xsl:template match="mail:password">
<xsl:apply-templates select="./mail:password"/>
</xsl:template>
<xsl:template match="mail:email">
<username>
<xsl:value-of select="."/>
</username>
</xsl:template>
<xsl:template match="mail:password">
<password>
<xsl:value-of select="."/>
</password>
</xsl:template>
</xsl:stylesheet>


This XSLT transformer reads the source XML file and converts it to the destination XML format.After creating the XSLT file, we need to apply it to the incoming xml file before parsing it.

InputStream xslt = this.getClass().getResourceAsStream("mail_to_user.xslt");
try {
TransformerFactory.newInstance().newTransformer(new StreamSource(xslt))
.transform(src, res);
} catch (Exception e) {
e.printStackTrace();
}

The only difference is that we pass the XSLT document as an StreamSource object to the Transformer to use it before converting the incoming StreamSource object to the equivalent OutputStream.So we can convert any format of incoming messages to our desired format before extracting information.

No comments: