Hack 54 Generate SVG with XSLT

   

figs/moderate.gif figs/hack54.gif

With XSLT, you can create and alter SVG documents on the fly.

Scalable Vector Graphics [Hack #66] provides an interoperable framework for creating graphics that, as XML documents, can be easily stored, transported, displayed in a web browser, and integrated into web pages and other applications. Two-dimensional line art, charts, and art of all kinds are possible with SVG. This hack will walk you through a simple business application using SVG and XSLT.

SVG isn't always simple markup, but using XSLT you can use simple markup, separate from SVG, that can be transformed or merged into more complex SVG markup. For example, let's say that your company regularly produces charts that reflect quarterly sales figures. You can keep the sales data in a small XML document and then integrate it into SVG with XSLT.

sales-2004Q2.xml (Example 3-45) is a brief document that expresses sales figures for the Eastern United States as a percentage of a $100,000 USD target.

Example 3-45. sales-2004Q2.xml
<?xml version="1.0" encoding="UTF-8"?>     <sales>  <region>   <title>Eastern Region Quarterly Sales (Second/'04)</title>   <key1 area="New York Area">.95</key1>   <key2 area="Virginia Area">.89</key2>   <key3 area="Maryland Area">.67</key3>   <key4 area="Connecticut Area">.65</key4>   <key5 area="Delaware Area">.45</key5>  </region> </sales>

With XSLT, you can merge this data with an SVG document that produces a bar graph using the stylesheet bar.xsl (Example 3-46).

Example 3-46. bar.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="sales"> <svg width="650" height="500">  <g  transform="translate(0 500) scale(1 -1)">   <line  x1="30" y1="20" x2="30" y2="450"    style="fill:none;stroke:rgb(0,0,0);stroke-width:2"/>   <line  x1="30" y1="20" x2="460" y2="20"    style="fill:none;stroke:rgb(0,0,0);stroke-width:2"/>  </g>    <xsl:apply-templates select="region"/> </svg> </xsl:template> <xsl:template match="region">  <g  transform="translate(30 479) scale(1 -430)">   <rect x="30" y="0" width="50" height="{key1}"    style="fill:rgb(255,0,0);stroke:rgb(0,0,0);stroke-width:0"/>   <rect x="100" y="0" width="50" height="{key2}"    style="fill:rgb(0,255,0);stroke:rgb(0,0,0);stroke-width:0"/>   <rect x="170" y="0" width="50" height="{key3}"    style="fill:rgb(255,255,0);stroke:rgb(0,0,0);stroke-width:0"/>   <rect x="240" y="0" width="50" height="{key4}"    style="fill:rgb(0,255,255);stroke:rgb(0,0,0);stroke-width:0"/>   <rect x="310" y="0" width="50" height="{key5}"    style="fill:rgb(0,0,255);stroke:rgb(0,0,0);stroke-width:0"/>  </g>  <g  transform="translate(29 60)">   <text  x="0px" y="320px"    style="text-anchor:end;fill:rgb(0,0,0);font-size:10;font-family:Arial">$25K </text>   <text  x="0px" y="215px"    style="text-anchor:end;fill:rgb(0,0,0);font-size:10;font-family:Arial">$50K </text>   <text  x="0px" y="107.5px"    style="text-anchor:end;fill:rgb(0,0,0);font-size:10;font-family:Arial">$75K </text>   <text  x="0px" y="0px"    style="text-anchor:end;fill:rgb(0,0,0);font-size:10;font-family:Arial">$100K </text>  </g>  <g >   <rect  x="430" y="80" width="25" height="15"    style="fill:rgb(255,0,0);stroke:rgb(0,0,0);stroke-width:1"/>   <rect  x="430" y="100" width="25" height="15"    style="fill:rgb(0,255,0);stroke:rgb(0,0,0);stroke-width:1"/>   <rect  x="430" y="120" width="25" height="15"    style="fill:rgb(255,255,0);stroke:rgb(0,0,0);stroke-width:1"/>   <rect  x="430" y="140" width="25" height="15"    style="fill:rgb(0,255,255);stroke:rgb(0,0,0);stroke-width:1"/>   <rect  x="430" y="160" width="25" height="15"    style="fill:rgb(0,0,255);stroke:rgb(0,0,0);stroke-width:1"/>  </g>   <text  x="465px" y="92px"    style="fill:rgb(0,0,0);font-size:18;font-family:Arial">    <xsl:value-of select="key1/@area"/>   </text>   <text  x="465px" y="112px"    style="fill:rgb(0,0,0);font-size:18;font-family:Arial">    <xsl:value-of select="key2/@area"/>   </text>   <text  x="465px" y="132px"    style="fill:rgb(0,0,0);font-size:18;font-family:Arial">    <xsl:value-of select="key3/@area"/>   </text>   <text  x="465px" y="152px"    style="fill:rgb(0,0,0);font-size:18;font-family:Arial">    <xsl:value-of select="key4/@area"/>   </text>   <text  x="465px" y="172px"    style="fill:rgb(0,0,0);font-size:18;font-family:Arial">    <xsl:value-of select="key5/@area"/>   </text>  <g >   <text x="325px" y="20px"    style="text-anchor:middle;fill:rgb(0,0,0);font-size:24;font-family:Arial">     <xsl:value-of select="title"/>   </text>  </g> </xsl:template>     </xsl:stylesheet>

The template on line 4 matching sales sets up the SVG document, and the template on line 18 matching region fills it out. Lines 20, 22, 24, 26, and 28 use attribute value templates to include the content of the key1, key2, key3, key4, and key5 elements in sales-2004Q2.xml to set the height of the bars. The fill property, along with rgb(), controls the colors used. Play with the triplets in rgb() to change colors.

The value-of elements on lines 55, 59, 63, 67, and 71 grab the area attribute values on the key elements, placing this information on the right of the bars. The value-of on line 76 takes the content of the title element of the source and places it over the top of the bars.

Transform sales-2004Q2.xml with bar.xsl, saving the output to the file sales-2004Q2.svg, like this:

xalan -o sales-2004Q2.svg sales-2004Q2.svg bar.xsl

To see the result, open sales-2004Q2.svg in Netscape 7.1 with the Corel SVG plug-in installed (http://www.corel.com/svgviewer/), as shown in Figure 3-27.

Figure 3-27. sales-2004Q2.svg in Netscape 7.1 with Corel's SVG Viewer
figs/xmlh_0327.gif


3.25.1 See Also

  • Inspired by Sal Mangano's XSLT Cookbook (O'Reilly), pages 324-332.



XML Hacks
XML Hacks: 100 Industrial-Strength Tips and Tools
ISBN: 0596007116
EAN: 2147483647
Year: 2006
Pages: 156

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net