In pursuit of useful applications of SVG, I’ve become interested in using XSL transforms to turn data stored as XML into an SVG representation. I found a good starting article at A List Apart and it pointed to a great reference by Paul Grosso and Norman Walsh. These might be dated now, but I found them helpful starting points.


On to my example. We’re going to need some data. I had a look at StatsCan and found a report on population by sex and age group. I would have liked to get some more complete raw data, but it appears to cost a few bucks, so I’ll make do. I believe there are ways to scrape the data out of the table with just XSLT, but since this is a learning experience for me, I decided to skip that step by just pulling the numbers out by hand and creating an XML file with a text editor.

The results of my effort look a little like this:


<?xml version="1.0" encoding='UTF-8'?>
<populationbyageandsex>
<recordbyagegroup>
<agegroup>0-4</agegroup>
<kpersons>1695.9</kpersons>
<kmalepersons>868.0</kmalepersons>
<kfemalepersons>827.9</kfemalepersons>
</recordbyagegroup>

<recordbyagegroup>
<agegroup>90 and over</agegroup>
<kpersons>162.7</kpersons>
<kmalepersons>42.6</kmalepersons>
<kfemalepersons>120.1</kfemalepersons>
</recordbyagegroup>
</populationbyageandsex>

The root node is called “populationbyageandsex” and each record (or row of data) is kept in a “recordbyagegroup”. Between the open and close tags for “recordbyagegroup” are the fields for that record. Each field has a unique name and the content (between the open and close tags) of the element is the value of the field. The format is something I just made up for this example, XML is nice that way.

The next step was to write the XSL transformations that would understand the data well enough to create a chart in SVG. At first I didn’t understand that XSLT is a complete programming language (it may not have been at points in the past, but that’s what it is now). I also didn’t realize that XSLT is designed for transforming one flavour of XML to another. I guess I was just pretty confused by the whole thing (that’s not to say that I’m not still a little muddy on the subject).

Here’s what the XSLT looks like now that it works:


<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl=”http://www.w3.org/1999/XSL/Transform” version=”1.0″>

<xsl:output method=”xml”
omit-xml-declaration = “no”
indent=”yes”
version=”1.0″
doctype-system = “-//W3C//DTD SVG 1.0//EN”
doctype-public = “http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd”
/>

<xsl:template match=”/populationbyageandsex”>
<svg viewBox=”0 0 3000 2000″ xmlns:svg=”http://www.w3.org/2000/svg” version=”1.1″ xmlns:xlink=”http://www.w3.org/1999/xlink”>
<xsl:apply-templates select=”recordbyagegroup”/>
</svg>
</xsl:template>

<xsl:template match=”recordbyagegroup”>
<xsl:call-template name=”plot-line”>
<xsl:with-param name=”length” select=”kpersons”/>
<xsl:with-param name=”position” select=”position()”/>
<xsl:with-param name=”label” select=”agegroup”/>
</xsl:call-template>
</xsl:template>

<!– length is the length of the bar for this data value –>
<!– position is ordinal value of this data point in the data set –>
<!– label is the text used to describe the data set –>
<xsl:template name=”plot-line”>
<xsl:param name=”label”/>
<xsl:param name=”length”/>
<xsl:param name=”position”/>
<xsl:element name = “polyline” >
<xsl:attribute name=”points”> 10,<xsl:value-of select=”$position * 100″/>,<xsl:value-of select=”$length”/>,<xsl:value-of select=”$position * 100″/> </xsl:attribute>
<xsl:attribute name=”fill”> none </xsl:attribute>
<xsl:attribute name=”stroke”> black </xsl:attribute>
<xsl:attribute name=”stroke-width”> 30 </xsl:attribute>
</xsl:element>
<xsl:element name = “text” >
<xsl:attribute name=”x”> <xsl:value-of select=”$length + 10″/> </xsl:attribute>
<xsl:attribute name=”y”> <xsl:value-of select=”$position * 100 + 20″/> </xsl:attribute>
<xsl:attribute name=”font-size”> 40 </xsl:attribute>
<xsl:attribute name=”stroke”> red </xsl:attribute>
<xsl:attribute name=”stroke-width”> 1 </xsl:attribute>
<xsl:value-of select=”$label”/>
</xsl:element>

</xsl:template>

</xsl:stylesheet>

Look at the template called “plot-line” in the code. A template in XSLT seems to work a whole lot like a function in other programming languages. It’s called using the xsl:call-template element and the parameters are each passed in a xsl:with-param tag. The named parameters show up in the template using xsl:param elements.

The xsl:value-of element does all the substitution in my example (there may be other and better ways, but I don’t know them yet). The select attribute of the value-of tag can refer to several expressions. A tag in the current node like the places that use select=”kpersons”. A function from XPath like select=”position()” (this gets the ordinal of the current node in a collection). A formula like select=”$position * 100″. Note that I did a bad thing here - I named a parameter “position” and I filled its value from the position() function. I realize this can be a little confusing, I’ll fix it later. In the formula case, $position refers to the parameter position from the xsl:param name=”position” line.

The plot-line template produces one line of the chart and a text label for it. It does this with the xsl:element tag. This tag inserts an element into the output. The attributes of the element are nested with xsl:attribute tags. There’s not really too much more to it once you know that, but I’ll go over some more details later. Oh, here’s the SVG - you’ll need an SVG viewer to display it.


Can’t view SVG? There’s an explanation of how to view SVG on SVGBasics.com.

Other recent posts in these categories: