Converting Proprietary Files to SVG with Perl

   



Generating SVG with XSLT

You need to install an XSLT processor on your machine so that you can apply XSL stylesheets to XML documents. If you haven't already done so, copy the Instant Saxon executable on the CD-ROM to a convenient directory on your PC and then add this directory to your PATH variable. An example of invoking this executable is given below:

saxon abc.xml abc.xsl >abc.svg

The preceding invocation applies the XSL stylesheet abc.xsl to the XML document abc.xml and then redirects the output to the file abc.svg.

If you want to see the list of options that you can use with saxon, you can type the following,

saxon -?

and you will see something like this:

No source file name SAXON 6.2.2 from Michael Kay Usage: saxon [options] source-doc style-doc {param=value}... Options:   -a              Use xml-stylesheet PI, not style-doc argument   -ds             Use standard tree data structure   -dt             Use tinytree data structure (default)   -o filename     Send output to named file or directory   -m classname    Use specified Emitter class for xsl:message output   -r classname    Use specified URIResolver class   -t              Display version and timing information   -T              Set standard TraceListener   -TL classname   Set a specific TraceListener   -u              Names are URLs not filenames   -w0             Recover silently from recoverable errors   -w1             Report recoverable errors and continue (default)   -w2             Treat recoverable errors as fatal   -x classname    Use specified SAX parser for source file   -y classname    Use specified SAX parser for stylesheet   -?              Display this message

XSLT is an extremely powerful tool that can require a substantial amount of time and effort to gain a high level of mastery. With that in mind, let's start with a relatively easy example of an XML file containing a set of object tags that we can 'map' to an SVG document by means of an XSL stylesheet. Listing 17.13 contains the sample XML document  xsltToSVG1.xml, which specifies a rectangle, a polygon, and an ellipse by way of standard XML tags; Listing 17.14 contains the XSL stylesheet  xsltToSVG1.xsl that can be applied to  xsltToSVG1.xml in order to generate an SVG document.

Listing 17.13 xsltToSVG1.xml

start example
<?xml version="1.0"?> <objects>   <object>     <type>rect</type>     <x>50</x>     <y>50</y>     <width>100</width>     <height>50</height>     <style>fill:red</style>    </object>   <object>     <type>polygon</type>     <points>300,50 450,50 350,100 300,150</points>     <style>fill:blue</style>   </object>   <object>     <type>ellipse</type>     <cx>300</cx>     <cy>100</cy>     <rx>100</rx>     <ry>50</ry>     <style>fill:blue</style>   </object> </objects>
end example

Remarks

The first point to observe in Listing 17.13 is the objects tag and the object tag; these were chosen in an arbitrary manner as a generic mechanism for including multiple SVG-like elements. In this particular case, Listing 17.13 contains the necessary attributes for specifying three SVG elements: a rectangle, a polygon, and an ellipse.

Listing 17.14 xsltToSVG1.xsl

start example
<?xml version="1.0"?> <xsl:stylesheet      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"      version="1.0">  <xsl:template match="/">   <svg>     <g>       <xsl:apply-templates/>     </g>   </svg>  </xsl:template>  <xsl:template match="objects/object">   <xsl:for-each select=".">     <xsl:choose>       <xsl:when test="./type = 'rect'">         <xsl:call-template name="createRectangle"/>       </xsl:when>       <xsl:when test="./type = 'polygon'">        <xsl:call-template name="createPolygon"/>      </xsl:when>     </xsl:choose>   </xsl:for-each>  </xsl:template>  <xsl:template name="createRectangle">    <xsl:variable name="x"      select="./x"/>    <xsl:variable name="y"      select="./y"/>    <xsl:variable name="width"  select="./width"/>    <xsl:variable name="height" select="./height"/>    <xsl:variable name="style"  select="./style"/>    <rect x="{$x}"         y="{$y}"          width="{$width}" height="{$height}"          style="{$style}"/>  </xsl:template>  <xsl:template name="createPolygon">    <xsl:variable name="points" select="./points"/>    <xsl:variable name="style"  select="./style"/>    <polygon points="{$points}" style="{$style}"/>  </xsl:template> </xsl:stylesheet>
end example

Remarks

Listing 17.14 starts by matching the root element ('/'), generating the outermost SVG element, and then invoking the main loop of the XSL stylesheet via the XSL code in bold, as listed below:

<xsl:template match="/">   <svg>     <g>       <xsl:apply-templates/>     </g>   </svg> </xsl:template>

The main loop in Listing 17.14 is executed by means of the following type of XSL statement,

<xsl:for-each select=".">   <!- add processing logic for each node here -> </xsl:for-each>

and the logic that decides which XSL template to invoke is based on the content of each type element, as shown below:

<xsl:template match="objects/object">   <xsl:for-each select=".">     <xsl:choose>       <xsl:when test="./type = 'rect'">        <xsl:call-template name="createRectangle"/>       </xsl:when>       <xsl:when test="./type = 'polygon'">         <xsl:call-template name="createPolygon"/>       </xsl:when>     </xsl:choose>   </xsl:for-each> </xsl:template>

Notice that the <xsl:when> logic in the preceding loop only checks for object elements that contain a type element whose value is either rect or polygon (hence, the ellipse element is ignored). Whenever one of these two matching elements is encountered, an XSL template is explicitly invoked: one template generates an SVG rect element and the other template generates an SVG polygon element.

The createRectangle template for generating an SVG rect element is:

<xsl:template name="createRectangle">   <xsl:variable name="x"      select="./x"/>   <xsl:variable name="y"      select="./y"/>   <xsl:variable name="width"  select="./width"/>   <xsl:variable name="height" select="./height"/>   <xsl:variable name="style"  select="./style"/>   <rect x="{$x}"         y="{$y}"         width="{$width}" height="{$height}"         style="{$style}"/> </xsl:template>

The createRectangle template requires the value of five elements from the XML document: the x-coordinate and y-coordinate of the upper-left corner of the rectangle, the width and height of the rectangle, and the style attribute of the rectangle.

The createPolygon template for generating an SVG polygon element is:

<xsl:template name="createPolygon">   <xsl:variable name="points" select="./points"/>   <xsl:variable name="style"  select="./style"/>   <polygon points="{$points}" style="{$style}"/> </xsl:template> 

The createPolygon template is shorter than the createRectangle template because it only requires the points element and the style element from the XML document.

Although Listing 17.14 contains a significant amount of XSL code, it has been organized in a structured fashion to make it easier for you to understand the logic of each component. Incidentally, a good exercise would be to write the corresponding code required for processing an SVG ellipse element. When you are done, add your own SVG-based elements to the XML document-and the corresponding code in the XSL stylesheet. It will help you attain a good comfort level with the XSL code.



   



Fundamentals of SVG Programming. Concepts to Source Code
Fundamentals of SVG Programming: Concepts to Source Code (Graphics Series)
ISBN: 1584502983
EAN: 2147483647
Year: 2003
Pages: 362

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