Friday, January 6, 2012

How to apply XSLT translation on an input xml using java.xml.transform apis


Almost all applications that deal with XML will have the necessity to transform the xml from one form to another. XSLT (XML Style Sheet Language Transformations) is one of the most popular ways of defining the transformations for XML document.

A transformation defined in XSLT describes rules for transforming a source xml into a result xml. The result XML can be of a completely different structure of that of the source XML. The transformation is achieved by associating patterns with templates. A pattern is matched against elements in the source XML. The result XML is constructed from the source XML by filtering, reordering and/or by adding arbitrary structures using the data from the source xml

Let us take an example and discuss how we can apply an xslt translation on an xml file using Java XML transformation APIs





The xml is assumed to be stored as bookStoreXml.xml and has the following content

<?xml version="1.0" encoding="ISO-8859-1"?>
<results>
<book category="COOKING">
  <title lang="en">Everyday Italian</title>
  <author>Giada De Laurentiis</author>
  <year>2005</year>
  <price>30.00</price>
  <date>2011-10-20</date>
</book>

<book category="CHILDREN">
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
  <date>2008-01-10</date>
</book>

<book category="WEB">
  <title lang="en">XQuery Kick Start</title>
  <author>James McGovern</author>
  <author>Per Bothner</author>
  <author>Kurt Cagle</author>
  <author>James Linn</author>
  <author>Vaidyanathan Nagarajan</author>
  <year>2003</year>
  <price>49.99</price>
  <date>2008-01-10</date>
</book>

<book category="WEB">
  <title lang="en">Learning XML</title>
  <author>Erik T. Ray</author>
  <year>2003</year>
  <price>39.95</price>
  <date>2007-01-10</date>
</book>

</results>

Let us say our requirement is to translate the XML to an HTML form with each book node in XML be a row in a table element.

First, we will create an XSLT that will do the transformation. The xslt is assumed to be stored as bookhtmltransform.xsl and will have the following content

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  >
<xsl:output method="html"></xsl:output>
<xsl:template match="/">
<html>
        <body>
                <table>
                        <thead>
                                <th>Title</th>
                                <th>Author</th>
                                <th>Price</th>
                        </thead>
                <tbody>
                        <xsl:for-each select="results/book">
                                <tr>
                                <td><xsl:value-of select="title"/> </td>
                                <td><xsl:value-of select="author"/> </td>
                                <td><xsl:value-of select="price"/> </td>
                                </tr>
                        </xsl:for-each>
                </tbody>
                </table>
        </body>
</html>
</xsl:template>
</xsl:stylesheet>


The following Java code will do the transformation.

import java.io.ByteArrayOutputStream;
import java.io.File;

import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

public class TestXSLT {

        public static void main(String[] args) {

                String returnHtml = "";
                String xmlFileName = "bookStoreXml.xml";
                String xsltFileName = "bookhtmltransform.xsl";
        try {
            Source xmlSource = new StreamSource(new File(xmlFileName));
            Source xsltSource = new StreamSource(new File(xsltFileName));

            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer = factory.newTransformer(xsltSource);
            ByteArrayOutputStream bOut = new ByteArrayOutputStream();
            transformer.transform(xmlSource, new StreamResult(bOut));

            bOut.close();
            returnHtml = bOut.toString();

            System.err.println(returnHtml);
        } catch (Exception e) {
                e.printStackTrace();
            System.err.println("Exception occurred: " + e);
        }
        }

}


The same code will work fine if the xml and xslt is in the form of String or an InputStream.

3 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Hi, I am learning how to use xml and xslt. Your help would be most appreciated.

    The third book in the xml file has multiple authors. Using

    xsl:value-of select="author"

    only selects the first author, so what to do about the other authors?
    Thanks

    ReplyDelete
    Replies
    1. If you want to print each author, instead of using xsl:value-of, you can use xsl:for-each.
      Please find the example below

      Delete

Blog Archive