Try the XML version of this page. If you have problems with it, consult the compatibility page.
The SVG utility is designed to help you to embed the SVG images that you generate using XSLT into an HTML page.
This page gives a simple example of using the SVG Utility to give a couple of charts based on some data within an HTML page. Say you had some data like:
<stats> <item><label>Jan</label><value>642</value></item> <item><label>Feb</label><value>527</value></item> <item><label>Mar</label><value>364</value></item> <item><label>Apr</label><value>843</value></item> <item><label>May</label><value>295</value></item> <item><label>Jun</label><value>250</value></item> <item><label>Jul</label><value>654</value></item> <item><label>Aug</label><value>828</value></item> <item><label>Sep</label><value>454</value></item> <item><label>Oct</label><value>732</value></item> <item><label>Nov</label><value>236</value></item> <item><label>Dec</label><value>546</value></item> </stats>
You might want to generate a couple of SVG charts from this data - a bar chart and a line chart, for example. In this example, I use my:diagram
elements in my stylesheet to determine the types of charts that I want to create:
<my:diagrams> <my:diagram type="column" /> <my:diagram type="line" /> </my:diagrams>
First, I need to import the SVG utilities stylesheet into my stylesheet:
<xsl:import href="svg-utils.xsl" />
Second, I need to create a node-set variable within which there's one node per SVG image that I want to create. The nodes in this case are the my:diagram
elements within the stylesheet, so I access them:
<xsl:variable name="images" select="document('')/*/my:diagrams/my:diagram" />
Now I need to insert the script and the embed elements into my document. I use the utility to insert the script into the head of my HTML, passing the $images
variable as the value of the $images
parameter:
<html> <head> <title>SVG Chart Demonstration</title> <xsl:call-template name="insertSVGScript"> <xsl:with-param name="images" select="$images" /> </xsl:call-template> </head> <body> ... </body> </html>
In the body of the HTML page, I insert the embed elements by applying templates to the nodes held in the $images
variable:
<html> <head> ... </head> <body> <h1>SVG Chart Demonstration</h1> <p>The following charts are generated automatically using XSLT.</p> <xsl:apply-templates select="$images" mode="createEmbed" /> </body> </html>
Finally, I need to create the SVG for the two diagrams. To use the SVG Utility, I need to do this within a template in getSVG
mode:
<xsl:template match="my:diagram" mode="getSVG"> <xsl:variable name="points" select="$stats/item" /> <xsl:variable name="type" select="@type" /> <xsl:variable name="space" select="30" /> <xsl:variable name="width-height-ratio" select="2 div 3" /> <xsl:variable name="col-width" select="20" /> <xsl:variable name="col-gap" select="10" /> <xsl:variable name="point-width" select="5" /> <xsl:variable name="xaxis-width" select="count($points) * ($col-width + $col-gap)" /> <xsl:variable name="width" select="round($xaxis-width + (2 * $space))" /> <xsl:variable name="height" select="round($xaxis-width * $width-height-ratio + (2 * $space))" /> <xsl:variable name="max-value"> <xsl:for-each select="$points"> <xsl:sort select="value" order="descending" /> <xsl:if test="position() = 1"><xsl:value-of select="value" /></xsl:if> </xsl:for-each> </xsl:variable> <xsl:variable name="unit-multiplier" select="($xaxis-width * $width-height-ratio) div ($max-value * 1.05)" /> <svg width="100%" viewBox="0 0 {$width} {$height}" preserveAspectRatio="xMinYMin meet"> <!-- border around chart --> <rect width="{$width}" height="{$height}" style="fill: #CCC; stroke: black;" /> <!-- X Axis line --> <line x1="{$space}" y1="{$height - $space}" x2="{$width - $space}" y2="{$height - $space}" style="stroke: black;" /> <!-- Y Axis line --> <line x1="{$space}" y1="{$space}" x2="{$space}" y2="{$height - $space}" style="stroke: black;" /> <xsl:for-each select="$points"> <xsl:variable name="item-height" select="round(value * $unit-multiplier)" /> <xsl:variable name="xMin" select="$space + (count(preceding-sibling::item) * ($col-width + $col-gap))" /> <!-- Columns --> <xsl:choose> <xsl:when test="$type = 'column'"> <rect x="{$xMin + ($col-gap div 2)}" y="{$height - $space - $item-height}" width="{$col-width}" height="{$item-height}" style="fill: blue; stroke: black;" /> </xsl:when> <xsl:otherwise> <xsl:variable name="x" select="$xMin + ($col-gap div 2) + (($col-width - $point-width) div 2)" /> <xsl:variable name="y" select="$height - $space - $item-height - ($point-width div 2)" /> <rect x="{$x}" y="{$y}" width="{$point-width}" height="{$point-width}" style="fill: blue; stroke: black;" /> <xsl:variable name="next" select="following-sibling::item" /> <xsl:if test="$next"> <xsl:variable name="nextX" select="$xMin + $col-width + $col-gap * 1.5 + (($col-width - $point-width) div 2)" /> <xsl:variable name="nextY" select="$height - $space - ($point-width div 2) - round($next/value * $unit-multiplier)" /> <line x1="{$x + $point-width div 2}" y1="{$y + $point-width div 2}" x2="{$nextX + $point-width div 2}" y2="{$nextY + $point-width div 2}" style="stroke: blue;" /> </xsl:if> </xsl:otherwise> </xsl:choose> <!-- Column captions --> <text x="{$xMin}" y="{$height - $space div 3}" textLength="{$col-width}" style="font: Arial;"> <xsl:value-of select="label" /> </text> </xsl:for-each> </svg> </xsl:template>
If you have an SVG Viewer plug-in installed, you can view this example. The full stylesheet is available at .
/xslt/utilities/svg-utils.xml by Jeni Tennison; generated using SAXON 6.5 from Michael Kay