W3C/INRIA
2004, route des Lucioles
BP 93
Sophia Antipolis Cedex
France
Email: mf@w3.org, vincent.hardy@sun.com
Keywords: XSLT, Transformations
Abstract
This paper describes the use of XSLT in conjunction with SVG. Various techniques and usage scenarios are presented, and the advantages of each approach are also explained, showing the benefits of combining both languages.
SVG has been designed for interoperability with other W3C specifications, such as XLink and CSS. In particular the XSL Transformations (XSLT) Recommendation is a valuable tool for generating SVG graphics. This paper discusses techniques that can be used to combine SVG and XSLT and illustrates them through various examples.
Part I provides an overview of the XSLT language. Originally designed for the Extensible Stylesheet Language (XSL), XSLT is now widely used as a general transformation language, which can transform any document of a given XML type into another of a different type. XML-to-HTML transformations are increasingly popular with the inclusion of XSLT processors in major Web browsers. SVG can also be generated via an XSLT transformation, providing a way to generate graphical representations of a wide range of XML data.
Part II describes popular techniques for generating SVG using an XSLT transform from XML data, producing a visual presentation of it. Examples of applications include reporting statistics from structured data via graphical charts, rendering mathematical equations from MathML content or displaying molecule diagrams from Chemical Markup Language documents. Various strategies exist for defining and applying transforms that generate SVG, which are shown here. The advantages of each approach are also explained, showing all the benefit of combining XSLT and SVG, such as the separation of concerns or the definition of constraints in a graphic.
Part III describes concrete instances where XSLT and SVG are associated, showing how XSLT can perform complex operations in a simple and concise way, and proving that it provides a valid alternative to using standard programming languages and the DOM. The first example explains how to write a transform to generate an animated board from a chess game expressed in XML format (using ChessGML). The second shows how to generate animated statistical graphs from code metrics.
Originally, XSL was designed to add style to an XML document using Formatting Objects (FO), an XML vocabulary describing paged documents, with advanced formatting features such as vertical writing modes, widow/orphan control or automatic table of content generation. Early in the definition of XSL, the specification was split in two: XSL Transformations (XSLT), which defines the process to transform the XML instance into an FO, and XSL which only describes the semantics and rendering of each formatting object and property.
XSLT was designed to be more general than for use within XSL, allowing the transformation of documents into documents of any XML type, not only FO. This allowed XSLT to be used in a much more general context, allowing users to transform XML documents into widely supported vocabularies, such as HTML.
XSLT is a functional language, expressed in XML syntax. An XSLT transform (or stylesheet) is in essence a list of templates, each defining a mapping between an object from the source document (element, attribute, comment, etc.) to an object in the output document. On top of that, XSLT defines standard programming language constructs like conditionals and loops.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform version="1.0"> <xsl:template match="foo"> <bar><xsl:apply-templates/></bar> </xsl:template> ... </xsl:stylesheet>
As XSLT can produce any type of XML, SVG is a good choice as it makes it possible to produce graphical representations of documents.
<data> <datum>23</datum> <datum>94</datum> <datum>55</datum> </data>
The simple stylesheet below transforms our data into a histogram in SVG. Of course the stylesheet can process any input file of that type, with any number of data.
Stylesheet:<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <svg xmlns:svg="http://www.w3.org/2000/svg" viewBox="0 0 {10*(count(data/datum)+1)} 100"> <xsl:for-each select="data/datum"> <rect x="{10*position()}" y="{100- .}" width="10" height="{.}" fill="red" stroke="black"/> </xsl:for-each> </svg> </xsl:template> </xsl:stylesheet>Result:
As the example above shows, XPath expressions can be included within SVG markup, for computing the value of numeric attributes from values in the source documents. The value of the attribute is now an XPath Attribute Value Template, i.e. an XPath expression delimited by curly brackets in the output markup.
<xsl:stylesheet ...> <xsl:template ...> <svg ...> <rect x="{/data/datum * 10}" .../> ... </svg> </xsl:template> </xsl:stylesheet>
Using the XSLT construct called "Literal Result Element as Stylesheet", it is even possible to simplify a stylesheet further, to make it look somewhat like the destination document. Below is our example rewritten in this manner:
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xsl:version="1.0" viewBox="0 0 {10*(count(data/datum)+1)} 100"> <xsl:for-each select="data/datum"> <rect x="{10*position()}" y="{100- .}" width="10" height="{.}" fill="red" stroke="black"/> </xsl:for-each> </svg>
Simplifying even further it is possible to reduce the use of XSLT/XPath in an SVG file to the use of XSLT variables and XPath expressions only. The example below shows that by defining variables in the document and by referring them further down in the definition of primitives, it is possible to simplify the process of laying out a graphic by making the attribute of primitives depend on the value of those variables. Here, two circles are defined as well as a line connecting their centres. Modifying the graphic by changing the value of variables ensures that constraints are met, in this case that the line connect the centers of the circles.
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xsl:version="1.0"> <xsl:variable name="$x1" select="10"/> <xsl:variable name="$x1" select="12"/> <xsl:variable name="$x2" select="17"/> <xsl:variable name="$y2" select="36"/> <circle cx="{$x1}" cy="{$y1}" r="1" .../> <circle cx="{$x2}" cy="{$y2}" r="1" .../> <line x1="{$x1}" y1="{$y1}" x2="{$x2}" y2="{$y2}" .../> ... </svg>
Using this subset of XSLT/XPath has the consequence that an input document is no longer necessary to the stylesheet, as it is now self-referential. This means that a complete implementation of XSLT/XPath is not necessary and that the variable/expression mechanism could be included directly in the SVG renderer. The Batik SVG toolkit indeed supports it.
XPath Attribute Value Templates can of course be used in any SVG construct, not only geometric attributes. As an example below shows, it can also be advantageous to use them in animation markup.
<animate id="move{$move}" begin="{$move - 1}.end" xlink:href="#{$piece}" attributeName="x" attributeType="XML" dur="{$moveDuration}s" from="{$startX}" to="{$endX}" fill="freeze" restart="never"/>
Using XSLT constructs can not only be used as AVT in attributes but also in element content. This can be useful to refer to XSLT variables in scripts
This example shows how to insert the value of an XPath expression into ECMAScript code embedded in SVG
<script type="text/ecmascript"> function circle_click(evt) { var circle = evt.target; circle.setAttribute("x", <xsl:value-of select="$x1"/>*2); }</script>
Note that it is advised that code in <script> be included in a CDATA section, omitted here for clarity
We have seen that it can be interesting to use XSL stylesheet to express constraints, easily layout graphics and manage animation element dependencies. How can this be done in practice and where does it apply?
To apply XSL transformations, you can use a specialized software (e.g., a command line utility) which will take an XML document as an input, the XSL stylesheet to apply and will generate the result into the desired file.
For example, the Xalan software package (http://xml.apache.org/xalan-j) comes with a command-line utility which will let you apply an XSL transformation myStylesheet.xsl to an XML file myXMLFile.xml and output the result in result.svg as follows:
xalan -in myXMLFile.xml -xsl myStylesheet.xsl -out result.svg
However, there are many environments where it is not an option to use a stand-alone software package to perform XSL transformations and where using a software library is preferable. For example, the Java programming language defines a standard API for applying transforms to XML content (the javax.xml.transform package) and this API is part of the JDK 1.4 distribution.
The following lines of code apply a transformation to a DOM Document object:
import org.w3c.dom.Document; import javax.xml.transform.TransformerFactory; import javax.xml.transform.Transformer; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamSource; import javax.xml.transform.stream.StreamResult; .... TransformerFactory tFactory = TransformerFactory.newInstance(); String stylesheetId = ...; Transformer transformer = tFactory.newTransformer(new StreamSource(styleheetId)); Document doc = ...; // XML DOM to transform transformer.transform (new DOMSource(doc), new StreamResult(new FileOutputStream(outFileName))); ...
The above example is rather 'techy', but it is important to realize that the ability to integrate transformations in applications means that stylesheets can be applied in all kinds of contexts, client-side or server side. For example, it is easy to write a server component which would take a 'template' SVG stylesheet and populate it with custom information. Poscards are an example. Another example would be is a business card which can be transformed dynamically to incorporate a user's information.
A snippet of what such an stylesheet could look like:
<svg ....> ... <text ...><xsl:value-of select="user[@name]" /></text> ... </svg>
<game type="chess" variant="classic"> ... <moves ply-count="23"> <mp> <!-- 1. e4 e5 --> <m c="w"><p c="w" n="p"/><e2/><e4/></m> <m c="b"><p c="b" n="p"/><e7/><e5/></m> </mp> ...
Used by chess software but not easily readable otherwise. And it is not understood by browsers
The stylesheet first generates the initial chess board. It also defines each chess piece as an SVG font glyph (using the proper unicode codepoints)
Then, for each move, SMIL Animation elements are generated. For example, black's second move (2. ...exf4) produces the following SMIL Animation markup:
<animate id="move3" begin="move2.end" xlink:href="#m" attributeName="x" attributeType="XML" dur="2s" from="45" to="55" fill="freeze" restart="never"/> <animate xlink:href="#m" attributeName="y" attributeType="XML" begin="move2.end" dur="2s" from="38.5" to="48.5" fill="freeze" restart="never"/> <set xlink:href="#N" begin="move2.end+2s" dur="indefinite" attributeType="CSS" attributeName="visibility" to="hidden" restart="never"/>
The first two lines describe the black pawn's move, and the third specifies that after the pawn has moved, the white pawn that has just been taken must become invisible.
This example uses XSL techniques similar to the ones used in the ChessML demonstration. However, XML files and XSL documents where used in a slightly different way than in ChessML.
In the ChessML example, the SVG document was created by applying an XSL transformation directly to an XML source.
The Code Metrics example, comes out of the Batik open-source project where developers extract metrics from their code source. An input XML document defines the category to which each of the software component belongs. The tool generates metrics on the size of each component following a three-step process:
When it comes to generating SVG content, a number of options are possible. SVG content can be generated through the DOM API, by technologies such as PHP, CGI scripts or Active Server Pages. What are the advantages of using XSL?
First and foremost, XSL is declarative as it is itself an XML syntax. Therefore, it is a natural fit with all the other XML technologies which are so prominent today.
Second, XSL is ubiquitous in the sense that it can be applied in various contexts: client-side or server side. There is no requirement as to where the transformation applies.
Third, XSL provides an elegant way to express constraints (graphical constraints such as related element widths, layout constraints such as element positioning or time constraints such as dependencies between animation elements) easily and that is handy to generate some types of graphics (such as graphs).
In summary, XSL transformations generating SVG can be applied to simple or complex input structures and produce simple or complex SVG content.
There are a couple limitations to mention relative to the previous slide.
First, the constraints between graphical elements which can be expressed in an XSL stylesheet do not survive the transformation. Once the XSL transformation has been applied (and the constraints enforced) the constraints and no longer enforced if the SVG content changes.
For example, imagine the following XSL snippet:
<rect x="{$precedingRectX + 30}" y="..." ... />
which could produce an SVG with the following rectangles:
<rect x="0" y="..." .... /> <rect x="30" y="..." ... /> <rect x="60" y="..." ... />
The rectangles at the x position '30' was originally constrained by the position of the first rectangle. Similarly, the rectangle at position '60' was constrained by the second rectangle. However, modifying the position of the first rectangle through scripting (e.g., setting the first rectangle's x attribute to '20') will not contrain the x attributes on the second and consequently third rectangles to change (i.e., they will not become '50' and '70' respectively).
A second limitation to the XSL and SVG 1.0 combination is related to text flow. SVG 1.0 does not flow text and this is a problem for XSL transformations which deal with arbitrary text for which it is difficult to compute flow. Line-breaking is a very difficult issue that is not easily (or not properly) solved by XSL transformations. The SVG working group has recognized that offering a solution to flow text is an important need and is working on adding it to the SVG recommendation (version 1.2).