Abstract
Dynamic graph generation has to be supported for effective Web applications. SVG and XForms are both XML languages.
Table of Contents
Business applications are multi-tier applications for long and IT managers prefer Web architecture for deployment because, most often, just the server-side needs installing and upgrading.
Even if users computers might be old and limited, their processors are not usually used at full capacity. On the contrary, servers are heavily concerned by the number of concurrent users and each and every optimization is interesting for them. The more the client is performing, the less data is transferred, the better for the server, for the network and for the response time.
Business applications are based on more or less complex forms and reports. Graphs are useful in screen reports, for dashboards typically: this is a must-have functionality for professional solutions.
For Web applications, when standard browsers are used, graphic
drawing at client-side is not that obvious. This is not supported by
HTML4, whether as a bitmap or as a vectorized image, and Javascript can't
help either.
Fortunately, SVG is natively supported by many browsers and more to come!
XForms Specifications are edited by the W3C.
Rich controls (input/select with types (date, email,...), constraints and dependencies) and AJAX data exchanges can be used without any Javascript instructions to be written.
XForms can be embedded in different XML languages, most commonly in (X)HTML.
XForms and HTML5 can cohabit on the same page.
XForms is based on an MVC architecture.
XRX is an acronym for XForms-REST-XQuery, which has been invented by Dan McCreary.
This is a Web architecture with a native XML Database engine and using only XForms, HTTP REST and XQuery allows to develop rich applications. No Javascript nor Java/PHP/.Net instructions are required and designers can develop such applications without being programmers.
Microsoft Excel is used by people for so long that it can be considered as a world reference for graphs.
Non-programmers can define and customize Excel graphs. In a
way, they develop their own tiny applications with them.
Web applications have to integrate graphs with such quality: multicoloured charts, mixed series with different manners to represent each, pie-charts/histograms/curves...
XSLTForms is an XForms 1.1 implementation based on XSLT 1.0 to compile well-formed HTML+XForms elements into HTML+CSS+Javascript.
To use it, no plug-in is required. This is very important for being used on the Web, not just for enterprise applications. This is also very useful not to have a different version of it for each version of each browser. Javascript compatibility problems might occur with a new version of browser but they have been limited for now.
Of course, XSLT 1.0 is very good for converting XML elements into other XML elements. But it might sound tricky when considering it for parsing XPath expressions, especially when comparing XSLT 1.0 with XSLT 2.0. Recursion is powerful but, for characters analysis, it is verbose. Nevertheless, it is very fast because the XSLT engine is itself compiled and XSLT 1.0 specifications are well supported in browsers.
This compile step allows to have optimized Javascript code to be executed by more or less fast Javascript engines.
XSLTForms is a versatile product and it can be improved with just a text editor because XSLT, CSS and Javascript are interpreted languages.
Graph2svg is a very nice product developed by Jakub Vojtíšek. Even if the generated graphs look now like old-fashioned Microsoft's Excel graphs, they are effectively as rich as them.
There are 3 different XSLT 2.0 stylesheets: one for graphs with one data serie, one for graphs with more data series and one for X-Y curves. One functionality is missing: gauges.
Those are complex XSLT 2.0 stylesheets with mathematical functions required.
This is, if necessary, a proof-of-concept that SVG is very good for graphs rendering.
Since Adobe SVG renderer was abandoned after Flash acquisition, no SVG plug-in renderer has been available.
Native SVG support, when present, is good enough for graphs.
Microsoft's recent decision to implement SVG in Internet Explorer is a key for success. Internet Explorer 9 will probably be embedded in the next future version of Windows (in 201?) but how many XP, Vista or Seven buyers, professionals or individuals, will upgrade their own current version of Internet Explorer (just consider today's discussions about Internet Explorer 6...)?
Flash renderer is a widely installed plug-in and the SVGWeb project is promising. Unfortunately, SVGWeb doesn't support namespaces and is more focused on dynamic interaction than on detailed rendering.
Silverlight is Microsoft's historical alternative for SVG and, of course, well supported by Internet Explorer 6+. SVG to XAML conversion tools can be found. Many are commercial products and cannot be used by a browser itself but there is also an XSLT 1.0 stylesheet available: Svg2xaml, even if it doesn't support all of standard graphic effects (text alignment,...).
SVG to VML conversion might also be considered.
This is the most intuitive approach: SVG elements are directly between HTML elements without intermediate elements such as HTML OBJECT or HTML EMBED.
Any XForms implementation has already to deal with inline XForms elements to be interpreted and replaced so it is not a problem. The use of the corresponding namespaces guarantees for potential name conflicts.
The XForms implementation has also to support AVT ({} notation in XSLT to allow XPath expressions within output attributes) because SVG uses a lot of attributes. AVT is not mentioned in XForms 1.1 Specifications but should be, as a possible extension, in the next ones.
For graphs, there might be more or less complex math calculations with more or less elements, for axes for example. XForms is not very powerful for such versatile constructs: xf:repeat and xf:bind can help but EXSLT math library is required and XPath 1.0 is not as powerful as XPath 2.0 (no conditional instructions,...).
Storing SVG images into, individual or not, XForms instances is another possibility.
Bindings can be defined to allow XForms input controls to interact with an SVG image, for attributes or elements values.
But, as for inline SVG, this is more appropriate for simple SVG images. This is not a modular approach and, whenever the graphic structure is evolving, there might be a lot to update.
This is precisely what Graph2svg is: values and parameters are grouped in an XML Document then an XSLT transformation is applied to produce an SVG image.
Values and parameters can be stored in one or more XForms instances which allows to bind controls and calculate constraints and permits exchanges with the server in the AJAX approach.
Such stylesheets can be considered as widgets because they can easily be reused with different values and parameters.
Defining different stylesheets for each rendering can be interesting for graphic designers to customize it and maintain it more easily. Maybe, Graph2svg stylesheets should be splitted in many, for example to distinguish pie-charts and histograms.
Graph2svg has to be rewritten for XSLT 1.0 so it can then be executed at client-side by the browser itself.
Another Graph2svg-like XSLT 1.0 stylesheet has to be written for rendering gauges.
Native SVG is selected when supported.
For Internet Explorer 6+ support, Svg2xaml has to be improved.
This is not a difficult point and a simple XSLT 1.0 stylesheet can demonstrate this.
Example of input XML document:
<gs:ongr xmlns:gs="http://graph2svg.googlecode.com"> <gs:title>Skills</gs:title> <gs:name>level</gs:name> <gs:value>3</gs:value> <gs:max>4</gs:max> </gs:ongr>
Simple XSLT 1.0 stylesheet:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:gs="http://graph2svg.googlecode.com" version="1.0">
<xsl:output method="xml" encoding="UTF-8"/>
<xsl:template match="gs:ongr">
<xsl:variable name="gmin">
<xsl:choose>
<xsl:when test="gs:min"><xsl:value-of select="gs:min"/></xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="gmax">
<xsl:choose>
<xsl:when test="gs:max"><xsl:value-of select="gs:max"/></xsl:when>
<xsl:otherwise>100</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.0" width="177" height="203.20624" style="overflow:hidden">
<defs/>
<ellipse cx="98" cy="98" rx="88" ry="88" transform="translate(-9.5,16.706237)" style="fill:#d0d0d0;fill-opacity:1;stroke:#333333;stroke-width:1"/>
<ellipse cx="98" cy="98" rx="78" ry="78" transform="translate(-9.5,16.706237)" style="fill:#fafafa;fill-opacity:1;stroke:#e0e0e0;stroke-width:2"/>
<text x="89.330505" y="14.316406" style="font-size:20px;text-anchor:middle;fill:#333333;fill-opacity:1;stroke:none;font-family:arial"><xsl:value-of select="gs:title"/></text>
<text x="88.5" y="145.70624" style="font-size:20px;text-anchor:middle;fill:#333333;fill-opacity:1;stroke:none;font-family:arial">
<tspan style="font-size:18px"><xsl:value-of select="gs:name"/></tspan>
</text>
...
<g transform="translate(-9.5,16.706237)">
<g transform="rotate({(gs:value - $gmin) * 270 div $gmax}, 98, 98)">
<path d="M 48.502525,147.49747 C 94.337187,94.337187 111.72494,80.612244 113.55635,82.443651 c 1.83141,1.831406 -11.89354,19.219159 -65.053825,65.053819" style="fill:#805c18;fill-opacity:0.6;stroke:#666666;stroke-width:1"/>
<ellipse cx="98" cy="98" rx="8" ry="8" style="fill:#987c84;fill-opacity:1;stroke:#666666;stroke-width:1"/>
</g>
</g>
</svg>
</xsl:template>
</xsl:stylesheet>
Resulting SVG:
XPath 2.0 is much richer than XPath 1.0: tests and loops have to be rewritten with XSLT 1.0 too.
Sequences can be replaced with node-sets (only FireFox 2.0 doesn't support XPath extra node-set() function).
XSLT 2.0 functions have to be replaced by named templates and intermediate variables.
Some tricks, such as "max((a,b))" replaced by "(a - b) * number(a > b) + b", can help too.
As an example, this XSLT 2.0 fragment:
<!-- begin of the SVG document for pie type-->
<svg:svg viewBox="0 0 {$width} {$height}">
<svg:desc><xsl:value-of select="$gra/ph/title"/></svg:desc>
<!-- type a title for pie -->
<svg:g>
<xsl:if test="count($gra/ph/title) > 0">
<svg:text x="{$width div 2}" y="{$titleMargin + $titleFontSize}"
text-anchor="middle"
font-family="Verdana" font-size="{$titleFontSize}"
fill="{if ($gra/ph/title/@color) then $gra/ph/title/@color else 'black'}" >
<xsl:value-of select="$gra/ph/title"/>
</svg:text>
</xsl:if>
</svg:g>
can be rewritten in XSLT 1.0 like this:
<!-- begin of the SVG document for pie type-->
<svg:svg viewBox="0 0 {$width} {$height}">
<svg:desc><xsl:value-of select="$gra/ph/title"/></svg:desc>
<!-- type a title for pie -->
<svg:g>
<xsl:if test="count($gra/ph/title) > 0">
<svg:text x="{$width div 2}" y="{$titleMargin + $titleFontSize}"
text-anchor="middle"
font-family="Verdana" font-size="{$titleFontSize}">
<xsl:attribute name="fill">
<xsl:choose>
<xsl:when test="$gra/ph/title/@color">
<xsl:value-of select="$gra/ph/title/@color"/>
</xsl:when>
<xsl:otherwise>black</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:value-of select="$gra/ph/title"/>
</svg:text>
</xsl:if>
</svg:g>
There are also much more complex XPath 2.0 to be rewritten.
As an example:
<xsl:variable name="maxYLabelWd" select="$labelFontSize * $labelFontWd *
max(for $a in (0 to $yAxisMarkCount) return
string-length(
if ($gra/ph/@stacked='percentage') then
concat(m:Round(($yAxisMin + $a * $yAxisStep) * 100, $yAxisStep), '% ')
else
string(m:Round($yAxisMin + $a * $yAxisStep, $yAxisStep))
) + (if ($gra/ph/@yAxisType='log') then 2 else 0)
)"/>
EXSLT math library is not supported in browsers but algorithms for trigonometric and logarithmic functions can be implemented for XSLT 1.0.
For example, the math:atan() function can be rewritten with an XSLT 1.0 named template:
<xsl:variable name="eps">0.0000000000000001</xsl:variable>
<xsl:template name="atan">
<xsl:param name="x"/>
<xsl:param name="k" select="3"/>
<xsl:param name="y" select="$x * $x"/>
<xsl:param name="i" select="-1"/>
<xsl:param name="u" select="$x * $y"/>
<xsl:choose>
<xsl:when test="$u > $eps">
<xsl:call-template name="atan">
<xsl:with-param name="x" select="$x + $u * $i div $k"/>
<xsl:with-param name="k" select="$k + 2"/>
<xsl:with-param name="y" select="$y"/>
<xsl:with-param name="u" select="$u * $y"/>
<xsl:with-param name="i" select="-$i"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$x"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Text positioning, when not to the left, requires font metrics to be used to calculate the corresponding left position.
Apache FOP comes with a font metrics reader (TTFReader) which generates an XML file for each font file, TTF format being supported.
Some dot-dash line formats have to be added.
Complex content rendering can be obtained by the xf:output control with the extra XPath serialize() function associated with the mediatype attribute being set to "image/svg+xml".
Another extra XPath function is required: transform(). This function allows applying an XSLT 1.0 stylesheet to an instance node.
Even if XSLTForms can generate XHTML, it is usually asked to generate HTML for compatibility purposes with Javascript frameworks. This implies that inline SVG is not allowed, even for browsers with native SVG, and that the OBJECT element has to be used.
Because SVG has an XML notation, it can easily be manipulated in XForms with XPath or XSLT. SVG can describe standard graphs to be generated dynamically at client-side and, so, SVG can reduce servers load. Using XSLT allows to define powerful SVG widgets to be used in different pages with different options.
SVG support is a key element for effective XML applications.