Introduction
This article presents several XSLT stylesheets for visualizing numerical data rows contained, as you may have guessed, within XML files. The article explains the details of stylesheet setup and the template design rationale.
Stylesheets for the following types of charts are described:
This article assumes you are familiar with XSLT 1.0 and, to some extent, CSS Level 1.0 standards.
Much in common
- Input XML structure
Templates are tuned to process files with the following structure:
<root>
<data date="date-string">
<first-component-name>first-component-value</first-component-name>
<second-component-name>second-component-value</second-component-name>
</data>
-->
</root>
Or, if you love schemas:
="1.0"
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xs:element name="data">
<xs:complexType>
<xs:all>
<xs:element name="a" type="xs:decimal" minOccurs="1" maxOccurs="1"/>
<xs:element name="b" type="xs:decimal" minOccurs="1" maxOccurs="1"/>
</xs:all>
</xs:complexType>
<xs:attribute name="date" type="xs:date" use="required"/>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
The following sample file is used to test all the stylesheets:
="1.0"
="text/xsl" ="stylesheet name"
<root>
<data date="2006-01-01">
<a>-1.5</a>
<b>2.5</b>
</data>
<data date="2006-01-02">
<a>-1.0</a>
<b>2.0</b>
</data>
-->
<data date="2006-01-07">
<a>1.5</a>
<b>1.3</b>
</data>
</root>
- Setup
Parameters are the same for all templates:
<xsl:call-template name="template-name">
-->
<xsl:with-param name="n" select="$resolution"/>
-->
<xsl:with-param name="nodeset" select="root/*"/>
-->
<xsl:with-param name="colorFirst">#008000</xsl:with-param>
-->
<xsl:with-param name="colorSecond">#B22222</xsl:with-param>
-->
<xsl:with-param name="colorEmpty">#DCDCDC</xsl:with-param>
</xsl:call-template>
However, most of the templates need additional info on the input node set:
- Simple and overlaid templates require the highest and lowest values for each component of the data row(s).
<!---->
<xsl:variable name="a_max_special">
<xsl:for-each select="root/data">
<xsl:sort select="a" data-type="number" order="descending"/>
<xsl:if test="position()=1">
<xsl:value-of select="a"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="a_max" select="number($a_max_special)"/>
- Stacked templates require the value of the highest and lowest component sums within data row(s).
<!---->
<xsl:variable name="sum_max_special">
<xsl:for-each select="root/data">
<xsl:sort select="sum(*)" data-type="number" order="descending"/>
<xsl:if test="position()=1">
<xsl:value-of select="sum(*)"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="sum_max" select="number($sum_max_special)"/>
- Normalized templates don't need any supplementary data.
Although you can obtain these values during the template runtime, "the best way to compute is to pre-compute" and assign the values to appropriate variables.
- Inner workings
Couple of words on template design.
- Bar charts. Bargraph-related stylesheets are made of two parts:
- template_name - the template you usually call. This is the "outer" template, which forms the base table of the chart;
- template2name (for bar charts, it can be disconnected with the "outer" template) - inner template, which forms the actual table row.
Bar charts are simple HTML <TABLE>
s, with <TD>
s filled with appropriate colors.
- Histograms. Histogram-related stylesheets are made of three parts:
- template_name - the template you may usually want to call. This is the "outer" template, which forms the base table of the chart;
- template_name_col - the template that forms the columns;
- template_name_cat - the template that builds the cells within columns.
Histograms are a little bit harder to build: the same old <TABLE>
with a single row and a number of <TD>
s, each being a data column. Each column is formed by multiple <P>
tags, with the number of tags equal to the resolution of the chart. Each paragraph is filled with the appropriate color.
- Customization
A simple CSS block controls a chart's look-and-feel:
<style>
table.bargraph // Controls bar charts
{
margin-top: -1px;
padding:0;
font-size: 15px;
// The main controller
// of the barchart's cell size
}
table.bargraph td.date // Controls 'date' column
{
width: 75px;
text-align:left;
}
table.histogram td // Controls histograms
{
width: 5px;
font-size: 1px;
padding-top: 10px;
}
table.histogram td p // Controls histogram cells
{
width: 20px; // Width...
height: 3px; // ...and height of a cell.
line-height: 0;
margin: 0 1px 1px 0;
padding: 0;
font-size: 1px;
}
</style>
- Limitations
- First visible tight spot is the number of components in a dataset that can be processed at a time. Simple and overlaid sheets can be extended for an arbitrary number of components in no time; extending others presents some problems, although shouldn't take too much time.
- Another problem is the complexity of stylesheets. While simple, overlaid, and normalized templates are fairly undemanding, stacked charts are heavyweight ones.
Charts
Inside the accompanying archive, you'll find the following stylesheets:
- Bar graphs.
- Bar-simple - distinct rows (2 per single date).
The most simple chart: comparison of components by date.
- Bar-overlaid - overlaid rows.
Nearly the same as the forerunner, but shows only a single row per date - components overlay each other.
- Bar-stacked - stacked bar chart.
Shows the contribution of individual items to the overall sum.
- Bar-normalized - stacked and 100%-normalized bar chart.
Shows the percentage of an individual item's contribution of the total value.
- Histograms.
- Hist-simple - distinct columns (2 per single date).
- Hist-overlaid - overlaid columns.
Note: strictly speaking, this and the two following charts cannot be called histograms; nevertheless, I'll use the MS Excel slang, which calls all 'horizontal' charts bar charts and all 'vertical' charts histograms (or column charts).
- Hist-stacked - stacked column chart.
- Hist-normalized - stacked and 100% normalized column chart.
History
- February 7th, 2006 - First version of the template set; positive values only.
- April 6th, 2006 - Second version; arbitrary range of values.
- April 25th, 2006 - Third version. Data file schema added; bar chart stylesheets optimized (resulting HTML is ~22% smaller compared with the previous version).