28 January 2009

Use XSLT to create a nice table in text

XSLT is a nice mechanism to transform a XML data file into something else. I had a case when I was to export some "messages" from a software to text and HTML. XSLT can perform both if the data source is an XML file. If you have the data as Java object JAXB can be used to convert Java objects to XML.

Lets say you have this XML file with a custom made format:
<messages>
<message>
<parameter name="Time">16:25:21.005</parameter>
<parameter name="Protocol">SIP</parameter>
<parameter name="Msg Size">376 byte(s)</parameter>
</message>
<message>
<parameter name="Time">16:25:21.015</parameter>
<parameter name="Protocol">SIP</parameter>
<parameter name="Msg Size">296 byte(s)</parameter>
</message>
<message>
<parameter name="Time">08:14:55.353</parameter>
<parameter name="Protocol">ISUP ITU</parameter>
<parameter name="Msg Size">59 byte(s)</parameter>
</message>
</messages>


This is the XSLT file to produce a nice text based table output:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/02/xpath-functions">
<xsl:output method="text" />

<xsl:template match="/messages">
<xsl:call-template name="tab" />
<!-- The parameter name are extracted from the first message -->
<xsl:for-each select="message[1]/parameter">
<xsl:value-of select="@name" />
<xsl:call-template name="tab" />
</xsl:for-each>
<xsl:call-template name="newline" />

<xsl:for-each select="message">
<xsl:text>Message #</xsl:text>
<xsl:value-of select="position()" />
<xsl:call-template name="tab" />
<xsl:for-each select="parameter">
<xsl:value-of select="." />
<xsl:call-template name="tab" />
</xsl:for-each>
<xsl:call-template name="newline" />
</xsl:for-each>
</xsl:template>

<xsl:template name="newline">
<xsl:text>&#10;</xsl:text>
</xsl:template>

<xsl:template name="tab">
<xsl:text>&#9;</xsl:text>
</xsl:template>

</xsl:stylesheet>


Sun Java 6 SE has build in XSLT support version 1.0. Please note that XSLT version 2.0 contains some new features. If you wish to use these you must plugin an external XSLT enginge (probably not that hard).

Use this Java code to transform:
package se.lesc.blog.xsltexample;

import java.io.StringWriter;

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

public class TransformExample1 {

public TransformExample1() throws TransformerException {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer;
transformer = transformerFactory.newTransformer(new StreamSource(getClass()
.getResourceAsStream("messageTable.xsl")));

StringWriter text = new StringWriter();

transformer.transform(new StreamSource(getClass().getResourceAsStream("messages.xml")),
new StreamResult(text));
System.out.println(text);
}

public static void main(String[] args) throws TransformerException {
new TransformExample1();
}
}

It will produce this output:
 Time Protocol Msg Size 
Message #1 16:25:21.005 SIP 376 byte(s)
Message #2 16:25:21.015 SIP 296 byte(s)
Message #3 08:14:55.353 ISUP ITU 59 byte(s)

No comments:

Post a Comment