Dynamic SVG graphs for XForms

From business data to high quality graphs within client-side MVC architecture


Abstract


Dynamic graph generation has to be supported for effective Web applications. SVG and XForms are both XML languages.


Table of Contents

Improving Business Web Applications Design
XML Languages for Web Applications
What is XForms?
What is XRX?
What about a Graph Renderer?
What users expect
Constraints
Existing components
XSLTForms
Graph2Svg Stylesheets
SVG Renderers
Possible architectures for SVG within XForms
Inline SVG
SVG instances
SVG Widgets as independent XSLT stylesheets
Integration in XSLTForms
Chosen components
Gauges with XSLT 1.0
Graph2svg for XSLT 1.0
Improving Svg2xaml
XSLTForms improvements
Conclusion

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.


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.

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 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 &gt; 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) &gt; 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) &gt; 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 &gt; $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>
 

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.