Creating Charts from General XML Files Using XSLT

JMSL can create charts from XML files that are written using a particular set of tags, but you can also generate charts from more general XML files. This is done by using XSL Transformations (XSLT) to transform other types of XML files into the type of XML file required by JMSL.

Example

Consider the following sales report in XML that does not use the tag names and structure that JMSL requires.

 

<?xml version="1.0" encoding="UTF-8" ?>

<sales>

    <region>

        <name>North America</name>

        <amount>102.890</amount>

    </region>

    <region>

        <name>Europe</name>

        <amount>87.654</amount>

    </region>

    <region>

        <name>Japan</name>

        <amount>93.895</amount>

    </region>

    <region>

        <name>Rest of World</name>

        <amount>37.985</amount>

    </region>

</sales>

 

To create a bar chart from this XML, it must be transformed into an XML file similar to the following

 

<?xml version="1.0" encoding="UTF-8" ?>

<Chart>

    <Array id="amount">

        <Number>102.890</Number>

        <Number>87.654</Number>

        <Number>93.895</Number>

        <Number>37.985</Number>

    </Array>

    <Array id="region">

        <String value="North America"/>

        <String value="Europe"/>

        <String value="Japan"/>

        <String value="Rest of World"/>

    </Array>

    <Attribute name="FontName" value="Serif"/>

    <Attribute name="FontSize" value="14"/>

    <ChartTitle><Attribute name="Title" value="Sales Chart"/></ChartTitle>

    <AxisXY>

        <AxisY>

            <AxisTitle><Attribute name="Title" value="Sales (in $million)"/>

            </AxisTitle>

        </AxisY>

        <AxisX>

            <AxisTitle><Attribute name="Title" value="Region"/></AxisTitle>

        </AxisX>

        <Bar y="#amount">

           <Attribute name="BarType" value="BAR_TYPE_VERTICAL"/>

           <Attribute name="Labels" value="#region"/>

           <Attribute name="LabelType"  value="LABEL_TYPE_Y"/>

           <Attribute name="FillColor" value="lime"/>

           <Attribute name="TextFormat">$###.###M</Attribute>

        </Bar>

    </AxisXY>

</Chart>

 

The following XSLT file can be used to perform this transformation.

(Download Code)

 

<?xml version="1.0" encoding="UTF-8" ?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

version="1.0">

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/">

        <Chart>

            <Array id="region">

                <xsl:for-each select="sales/region/name">

                    <String>

                        <xsl:apply-templates/>

                    </String>

                </xsl:for-each>

            </Array>

            <Array id="amount">

                <xsl:for-each select="sales/region/amount">

                    <Number>

                        <xsl:apply-templates/>

                    </Number>

                </xsl:for-each>

            </Array>

            <Attribute name="FontName" value="Serif"/>

            <Attribute name="FontSize" value="14"/>

            <ChartTitle>

                <Attribute name="Title" value="Sales Chart"/>

            </ChartTitle>

            <AxisXY>

                <AxisY>

                    <AxisTitle>

                        <Attribute name="Title" value="Sales (in $million)"/>

                    </AxisTitle>

                </AxisY>

                <AxisX>

                    <AxisTitle>

                        <Attribute name="Title" value="Region"/>

                    </AxisTitle>

                </AxisX>

                <Bar y="#amount">

                    <Attribute name="BarType" value="BAR_TYPE_VERTICAL"/>

                    <Attribute name="Labels" value="#region"/>

                    <Attribute name="LabelType" value="LABEL_TYPE_Y"/>

                    <Attribute name="FillColor" value="lime"/>

                    <Attribute name="TextFormat">$###.###M</Attribute>

                </Bar>

            </AxisXY>

        </Chart>

    </xsl:template>

</xsl:stylesheet>

 

While a complete discussion of XSLT is beyond the scope of this manual, note that most of the file is the same as the target. The XSL tags are in the “xsl” namespace. In this example, the key XSL tags are the two for loops that reformat the data. For instance, the region names are formatted by the fragment

 

<xsl:for-each select="sales/region/name">

   <String><xsl:apply-templates/></String>

</xsl:for-each>

 

where the path "sales/region/name" selects tags in the original XML file and the body of the tag

 

<String><xsl:apply-templates/></String>

is copied into the new file.

The given XSL document will work for similar documents with different data, but other XML document formats may require different XSL files.

The Java code required to implement this transformation is:

 

(Download Code)

 

import com.imsl.chart.JFrameChart;

import com.imsl.chart.xml.ChartXML;

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.parsers.DocumentBuilder;

import javax.xml.transform.TransformerFactory;

import javax.xml.transform.Transformer;

import javax.xml.transform.dom.DOMSource;

import javax.xml.transform.dom.DOMResult;

import org.w3c.dom.Document;

 

public class SampleSalesTransform {

 

    public static void main(String argv[]) throws Exception {

        String filenameXSL = argv[0];

        String filenameXML = argv[1];

 

        // Create an XML parser factory

        DocumentBuilderFactory factory =

                DocumentBuilderFactory.newInstance();

        factory.setNamespaceAware(true);

        DocumentBuilder builder = factory.newDocumentBuilder();

 

        // Parse the XSL file as an XML file

        Document docXSL = builder.parse(filenameXSL);

        DOMSource sourceXSL = new DOMSource(docXSL);

        sourceXSL.setSystemId(filenameXSL);

 

        // Create a transformation based on the XSL file

        TransformerFactory tFactory = TransformerFactory.newInstance();

        Transformer transformer = tFactory.newTransformer(sourceXSL);

 

        // Parse the input XML file

        Document docXML = builder.parse(filenameXML);

        DOMSource sourceXML = new DOMSource(docXML);

        sourceXML.setSystemId(filenameXML);

 

        // Transform the input XML file using the XSL transformer

        DOMResult result = new DOMResult();

        transformer.transform(sourceXML, result);

 

        // Create a chart from the transformed XML

        ChartXML chartXML = new ChartXML((Document) result.getNode());

        new JFrameChart(chartXML.getChart()).show();

    }

This program takes two arguments, the names of the XSL and XML file, and cre­ates a JMSL chart. The transformed XML exists only in memory and is not written to disk. This class will work with any (correct) XSL and XML file; it is not depen­dent on the details of this example. In the interests of simplicity, error handling and validation are not implemented, as they should be for a production implementation.

Also, for simplicity, this example is a desktop application. XML and XSLT are generally more useful as part of a server-side Web application. The above code can be used with JspBean to create a server-side XML/XSLT solution.



Visual Numerics - Developers of IMSL and PV-WAVE
http://www.vni.com/
PHONE: 713.784.3131
FAX:713.781.9260