Menu

The Visual Display of Quantitative XML

February 27, 2002

Fabio Arciniegas A.

The need to display quantitative data stored in XML files is quite common, even when transforming the most basic documents. For example, consider the following cases:

  • Number and type of hits registered in a server log;
  • Percentage of sales by an individual on an annual sales report;
  • Number of technical books vs. the total book count in a book list (almost every XML book in the world has that example);
  • Proportion of annotations per paragraph in a DocBook article

While quantitative XML data is everywhere, a less common thing to find is examples of effective ways to display such information. Most resources will merely show you how to use XSLT to convert XML data to HTML, which is often not nearly enough when you need to explain complex or large sets of data (see Figure 1). This article discusses the creation of useful graphical presentations of quantitative XML data using XSLT and SVG.

Outer Planet Orbits
Figure 1: Outer Planet Orbits -- sometimes graphics are the only way to rapidly consume complex and/or large information.

By using the Scalable Vector Graphics (SVG) language, we can create effective, attractive, and reusable visual representations of quantitative data for the Web. In what follows I discuss the principles and implementation of XSLT stylesheets that generate SVG output based on XML input, using as my example the location of establishments in an imaginary city.

A number of important technical graphic design principles are discussed along the way, but previous experience in the field isn't required, just a basic knowledge of XSLT. All examples include links to code commented in greater detail.

The principles of graphic excellence in this article are not new and certainly not my invention. They are a small subset adapted to the XSLT-SVG world, mainly from Edward Tufte's The Visual Display of Quantitative Information. I recommend you check the references provided if you are interested in this subject.

Setting up the Development Environment

You'll need an XSLT engine to transform the source data and an SVG viewer so that you can see the fruits of your work. There are several options for each and the examples will work with any compliant tool (see Antoine Quint's article on SVG tools for a list of current SVG viewers). For this article I will be using Xalan as the XSLT engine and the Adobe SVG viewer plug-in.

Night and the City

Online City guides often give their users quantitative data about restaurants and clubs in the form of text. A typical result page includes information such as the address and name of the club, plus an average user review. While this information is very useful for direct searches, an individual page per place with such data is not the best tool when you don't know your destination, or when you want to ask questions like "which areas have a higher concentration of highly-rated bars?"

Some of the most useful graphics are those that present many variables simultaneously so I have chosen for our exercise the problem of representing the location, popularity, name, type of establishment, address, and rating of the night-time attractions in a hypothetical city.

Our goal is to display multiple variables in an accessible and economic manner. The graphic most show position, type, name, and popularity information for over a dozen places in a 290 x 210 pixel area, plus enhance the original data by providing easy visual comparisons and answers to questions like that above. The final SVG result is shown in Figure 2 (make sure you have the Adobe plug-in).


Figure 2. Boggenburgh's night attractions (mouse over the places to see their details)

This example is meant to illustrate the first rule for creating graphics from XML data: avoid superfluousness. Graphics are a great way to manipulate and show data, but they are no better than a table or text if the data is not worth a diagram. Sometimes you have to mix text and graphics, but sometimes you have to drop graphics altogether, if they add no value.

Before we start coding a transformation, let's see the data we will be using as a source for our graphic, in listing 1.

Listing 1. A Peek Into The Source Data

(full source)

<?xml version="1.0"?>



<!-- This document summarizes data information

about the popularity and average occupancy during

weekends for the restaurants and clubs in the west

side of Boggenburgh. (this information, including

the name of the city, is of course fictitious -->



<night_attractions>

  <head>

   <city>Boggenburgh</city>

   <neighborhood>North West Side</neighborhood>

   <month>06</month>

   <year>2002</year>

  </head>

  <entries>

    <attraction type="bar">

      <name>Moe's</name>

      <abbrev_address>

         <number>2900</number>

         <street quad="NW">8</street>

      </abbrev_address>

      <average_rating>4</average_rating>

      <average_occupants>70</average_occupants>

    </attraction>



    <attraction type="restaurant">

      <name>Lou's Tavern</name>

      <abbrev_address>

         <number>2803</number>

         <street quad="NW">8</street>

      </abbrev_address>

      <average_rating>5</average_rating>

      <average_occupants>70</average_occupants>

    </attraction>

   </entries>

  <!-- many more entries here -->

</night_attractions>

Now that we have data worthy of be shown as a graphic, we will decompose each part of the solution into an SVG component and see how to generate it using XSLT.

The City Layout

The first item is the representation of the city blocks. Some cities, like Washington D.C and New York, are arranged in a rectangular grid. Other cities have somewhat consistent block sizes (e.g. Bogot√°). While in reality there are many exceptions to these rules, like diagonals and bigger blocks, for our city we will take an idealized view and assume a regular grid of blocks and streets. This convention will give us the chance to get warmed up with some simple SVG shapes and their systematic generation using XSLT.

So let's draw a simple city block as a rounded-corners rectangle. Listing 2 shows the SVG necessary.

Listing 2. A City Block

(source)

<?xml version="1.0"?> 

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"

  "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">



<!-- As you can see, the structure of this

simple SVG document is pretty straightforward: the

root element defines the size of the picture, and

the inner elements describe the constituent shapes

-->



<svg width="2in" height="2in" xmlns="http://www.w3.org/2000/svg">

   <title>Block</title>

   <desc>A City Block</desc>

   <!-- rx and ry define how round the corners of

      the rectangle should be -->

   <rect x="2" y="2" rx="5" ry="5" width="30" height="20"

         fill="none" stroke="black"/>

</svg>

Figure 3: A City Block (prototype-singleBlock.svg)

There are three important things to note about this simple listing.

   Related Reading

SVG Essentials

SVG Essentials
By J. David Eisenberg
Full Description
Index
Table of Contents

  • SVG's DOCTYPE and namespace. These values don't change; it's smart to have a basic template so you don't have to remember them every time you start from scratch.

  • Width and height of the image. We specify this on the root element. In this case we want a rectangle of side 2 inches.

  • The use of the basic shape rect for drawing the rounded-edge rectangle. Look in the references at the end of this article for a complete list of elements and their attributes.

Listing 3 shows a simple XSLT stylesheet to repeat these rounded squares, creating the basic layout for our map. Since XSLT doesn't have mutable variables the way most other languages do, we need to implement the repetition of blocks by calling the templates recursively. If you are comfortable with the idea of recursion, the following listing should be familiar, but if you have doubts, jump to the commented source code.

Listing 3. Creating the city grid with an XSLT repetition

(source)

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0"

	xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:variable name="blockHeight">20</xsl:variable>

<xsl:variable name="blockWidth">30</xsl:variable>

<xsl:variable name="streetWidth">10</xsl:variable>

<xsl:template match="/">

   <svg width="90in" height="90in"

          xmlns="http://www.w3.org/2000/svg">

      <title>Basic Blocks</title>

      <desc>A Simple Repetition Of Blocks</desc>

      <xsl:call-template name="blocks">

	 <xsl:with-param name="vertical">7</xsl:with-param>

	 <xsl:with-param name="horizontal">9</xsl:with-param>

      </xsl:call-template>

   </svg>

</xsl:template>

<xsl:template name="blocks">

    <xsl:param name="vertical"/>

    <xsl:param name="horizontal"/>

  <xsl:if test="$vertical &gt; 0">

      <xsl:call-template name="row_of_blocks">

	 <xsl:with-param name="number">

      	   <xsl:value-of select="$horizontal"/>

	 </xsl:with-param>

	 <xsl:with-param name="y">

      	   <xsl:value-of select="$vertical *

		      ($blockHeight + $streetWidth)"/>

	</xsl:with-param>

      </xsl:call-template>

      <xsl:call-template name="blocks">

	 <xsl:with-param name="vertical">

      	   <xsl:value-of select="$vertical - 1"/>

         </xsl:with-param>

	 <xsl:with-param name="horizontal">

      	   <xsl:value-of select="$horizontal"/>

	 </xsl:with-param>

      </xsl:call-template>

  </xsl:if>

</xsl:template>

<xsl:template name="row_of_blocks">

    <xsl:param name="number"/>

    <xsl:param name="y"/>

  <xsl:if test="$number &gt; 0">

   <rect x="{$number * ($blockWidth + $streetWidth)}" 

	 y="{$y}" 

	 rx="5" 

	 ry="5" 

	 width="{$blockWidth}" 

	 height="{$blockHeight}" 

	 fill="none" 

	 stroke="black"/>

   <xsl:call-template name="row_of_blocks">

	 <xsl:with-param name="number">

      	   <xsl:value-of select="$number - 1"/>

	 </xsl:with-param>

	 <xsl:with-param name="y">

      	   <xsl:value-of select="$y"/>

	</xsl:with-param>

   </xsl:call-template>

  </xsl:if>

</xsl:template>

</xsl:stylesheet>

Figure 4: All the City Blocks (right-click for source)

Marking the City Streets

Now that we have the city blocks, we need to mark the streets, which will showcase two common aspects of XSLT-SVG production: generating labels and series of numbers. Just as we did with the blocks, let's first manually create the SVG needed to put one label for a particular street, then we'll generalize the procedure using XSLT. In order to output the name of the street we use the SVG text element as shown in listing 4.

Listing 4: City Blocks with a Few Streets Marked

(complete source)


<!-- The rest of the file, including the surrounding svg

   element, remains the same as source for Figure 4 -->



<rect stroke="black" fill="none"

      height="20" width="30" ry="2"

      rx="2" y="168" x="306" />



<!-- STREET NAME -->



<text x="300" y ="200"

      style="font-family:Arial;

      font-size:8pt">8<tspan

	  style="font-size:7pt">th</tspan></text>



<rect stroke="black" fill="none"

      height="20" width="30" ry="2"

      rx="2" y="168" x="272" />



<!-- STREET NAME -->



<text x="268" y ="200"

      style="font-family:Arial;

      font-size:8pt">7<tspan

      style="font-size:7pt">th</tspan></text>



<rect stroke="black" fill="none"

      height="20" width="30" ry="2"

      rx="2" y="168" x="238"/>

Adding basic text with SVG is quite intuitive, just specify the upper left corner of the bounding box using the x and y attributes, and then add the desired style using CSS inside the style attribute. To tweak the presentation of the text, I have added a small tspan -- similar to a span element in an HTML document -- which allows us to apply a slightly different formatting for the "th" part of the street mark (in this business little details are really important). SVG has many fancy text options like aligning it to a curve path (see examples at this Sun's web site); these features are no doubt nice and useful for artistic production, but try to avoid them when developing graphics to represent data. They tend to clutter your information with unnecessary decoration and distract the user.

Here we have another rule of thumb: don't use snazzy effects only because they are available. Communicating complex data in an efficient manner is your goal. XSLT and SVG are your tools. Put the tools to the service of your goal, not the other way around.

Automating The Street Labels with xsl:number

The XSLT instruction xsl:number can be used in one of two basic ways. The first takes a pattern as its count attribute and outputs a number for each matching node. The second takes a specific number and formats it. The second form of xsl:number is ideal for our purposes because we are creating the city layout based on a fixed number of blocks, and we pass a parameter with the block number to the row_of_blocks template. Listing 5 shows how we use xsl:number to automate the street labeling.

As in previous listings, I embed here the clean-cut version for the XSLT aficionado, but a more comprehensively explained version is also provided.

Listing 5: Marking the streets with xsl:number

(full source)

<xsl:template name="row_of_blocks">

    <xsl:param name="column"/>

    <xsl:param name="row"/>

     <xsl:variable name="x">

      	   <xsl:value-of select="$column *

		      ($blockWidth + $streetWidth)"/>

     </xsl:variable>

     <xsl:variable name="y">

      	   <xsl:value-of select="$row *

		      ($blockHeight + $streetWidth)"/>

     </xsl:variable>



  <xsl:if test="$column &gt; 0">

   <rect x="{$x}" 

	 y="{$y}" 

	 rx="2" 

	 ry="2" 

	 width="{$blockWidth}" 

	 height="{$blockHeight}" 

	 fill="none" 

	 stroke="black"/>

    <!-- OUTPUT STREET NAME -->

    <!-- Since we don't want to put the street name on

         every intersection but only at the bottom, we must

         check that we are dealing with the lowest

         row before outputting the column -->

     <xsl:if test="$row = $cityHeight">

	   <text x="{$x - 6}" 

	         y="{$y + 32}" 

		 style="font-family:Arial; font-size:8pt">

                  <xsl:number value="$column"/>

           <tspan style="font-size:7pt; fill:#333333">

             <xsl:if test="$column  = 1">st</xsl:if>

             <xsl:if test="$column  = 2">nd</xsl:if>

             <xsl:if test="$column  = 3">rd</xsl:if>

             <xsl:if test="$column &gt; 3">th</xsl:if>

          </tspan>

        </text>

     </xsl:if>

   <xsl:call-template name="row_of_blocks">

	 <xsl:with-param name="column">

      	   <xsl:value-of select="$column - 1"/>

	 </xsl:with-param>

	 <xsl:with-param name="row">

      	   <xsl:value-of select="$row"/>

	</xsl:with-param>

   </xsl:call-template>

  </xsl:if>

</xsl:template>

After reading the listing above you might be wondering why we used xsl:number instead of simply outputing the value of the column; the answer is we might want to take advantage of the format attribute of number to provide a different output sequence. This is shown in the next listing, where we reuse the same xsl:number element, but this time we output the street names as the sequence "A", "B", "C", etc.

Listing 6: Marking letter streets with xsl:number

(full source)


<xsl:if test="$column = 0 and $row != 1">

  <text x="{$x + 23}" y="{$y + 2}" 

     style="font-family:Arial; font-size:8pt">

     <xsl:number value="$cityHeight - $row + 2"

         format="A"/>

  </text>

</xsl:if>

The result is nice alphabetical and numeric-labeled street signs as shown in Figure 5 below


Figure 5: Street Signs (right click for source)

Putting a Club on the Map

In order to display the establishments on the map we will use small PNG icons. We could also have drawn the icons in SVG, but using PNG icons gives us the chance to point out a few important issues about mixing raster images with SVG. We will use one PNG icon for each kind of establishment (restaurant.png, cafe.png, and bar.png). I chose the PNG (Portable Network Graphics) format not only because it is an increasingly popular one (similar to GIF without the licensing baggage), but because it is guaranteed that all compliant SVG viewers can display it. The only other guaranteed format is JPEG.

The syntax for including an image is simple and is shown below. Perhaps the only remarkable thing about this element is that SVG uses XLink for its href attribute; you can safely ignore the XLink details for now, but if you are interested you can read more about XLink in my article "What is XLink?".

<image xlink:href="booze.png"

	x="116" y="97" width="16"

	height="15"/>

Now that we have a complete city layout, we will begin using the data on the source file to position clubs, cafes, and restaurants. The process of figuring out the position and adding the appropriate icon is shown in the following template.

Listing 7 Putting clubs on the Map

(complete source)

<xsl:template match="attraction">

    <xsl:variable name="x">

    <xsl:value-of 

       select="number(abbrev_address/number) div 1000"/>

    </xsl:variable>

    <xsl:variable name="y">

    <xsl:value-of select="translate(abbrev_address/street,

       'ABCDEFGHI','123456789')"/>

    </xsl:variable>



   <xsl:if test="string-length(translate

       (abbrev_address/street,'ABCDEFGHI','')) = 0">

    <xsl:call-template name="point">

    <xsl:with-param name="x">

       <xsl:value-of select="$x"/>                

    </xsl:with-param>

    <xsl:with-param name="y">

       <xsl:value-of select="$cityHeight - ($y - 2)"/>        

    </xsl:with-param>

    <xsl:with-param name="x_proportion">

         <xsl:value-of select="$blockWidth + 

            $streetWidth"/>        

    </xsl:with-param>

    <xsl:with-param name="y_proportion">

         <xsl:value-of select="$blockHeight +

            $streetWidth"/>        

    </xsl:with-param>

    <xsl:with-param name="img">

         <xsl:value-of select="concat(@type,'.png')"/>

    </xsl:with-param>

    <xsl:with-param name="y_skew">

         <xsl:value-of select="(-16 - $streetWidth)*

            ($x*1000 mod 2)"/>

    </xsl:with-param>

    </xsl:call-template>

   </xsl:if>

 <!-- same for addresses on letter streets -->

</xsl:template>

There are many details included in the complete stylesheet to make sure the representation is correct. For example, we determine which side of the road the place should be according to whether its number is odd or even.

How "Hot" is a Destination?

Now that we have each place on the map we want to display its popularity using color, which will give us the opportunity to improve our point XSLT template and also to play with SVG's transparencies.

In theory, adding a colored halo to indicate popularity is really simple: map each level of popularity to a color and draw a circle around the place. In practice, this exposes two important details: choosing the value of a parameter based on a discrete set of options (a problem on the XSLT side) and creating transparencies (a problem on the SVG side).

To map each rating to a color value, we use the following Listing 8 code.

Listing 8 Mapping Discrete Values 


<xsl:variable name="color">    

<xsl:choose>

    <xsl:when test="average_rating=5">#F60C00</xsl:when>

    <xsl:when test="average_rating=4">#F66E00</xsl:when>

    <xsl:when test="average_rating=3">#F6B300</xsl:when>

    <xsl:when test="average_rating=2">#F6ED00</xsl:when>

    <xsl:when test="average_rating=1">#7BB105</xsl:when>

</xsl:choose>

</xsl:variable>

When starting with XSLT many people try something like

<xsl:if test test="average_rating = 5">

    <xsl:variable name="color">#F60C00</xsl:variable>

</xsl:if>

This does not work simply because once the xsl:if is closed, the variable goes out of scope. One to one mapping between input and the value of a variable is a very common problem when representing visual data, so make sure you keep the correct solution scheme (Listing 8) at hand.

As you may have guessed, the reason we are creating a color variable is so we can pass it to an improved point template. The revised version of point is shown below in Listing 9, where the style property fill-opacity is also used to make a nice blend between the icons and the popularity circles.

Listing 9: Point template with icon and color support

(full source)


<xsl:template name="point">



<xsl:param name="x"/>

<xsl:param name="y"/>

<xsl:param name="x_proportion" select="1"/>

<xsl:param name="y_proportion" select="1"/>

<xsl:param name="img" select="none"/>

<xsl:param name="x_skew" select="0"/>

<xsl:param name="y_skew" select="0"/>

<xsl:param name="color" select="black"/>

<xsl:param name="size" select="13"/>



<circle style="{concat('fill:',$color,

            '; fill-opacity:0.4')}"

        cy="{$y * $y_proportion + $y_skew + 8}" 

        cx="{$x * $x_proportion + $x_skew + 8}" 

        r="{$size}"

/>



<xsl:if test="$img != ''">

         <image xlink:href="{$img}" 

        x="{round($x * $x_proportion) + $x_skew}"

        y="{round($y * $y_proportion) + $y_skew}"

        width="16"

        height="16"/>

</xsl:if>



</xsl:template>

The final result of adding the popularity information to the graphic is shown below. Now with one glance, your users know the hot areas of the city.


Figure 6: Popularity Data Incorporated (right-click for source)

The Population Information -- Getting Dimensions Right

The population information is displayed with text and the mouse-over effect. However, if you look at the code closely, you will notice we could have passed a circle of radius dependent on the number of people who attend the place. Instead, I chose to keep the circles all of the same size and use them only for their colors. The reason why I haven't used this area resource more dramatically is because the average_occupants variable is a one dimensional piece of information (a point), while a circle is a two-dimensional representation (an area). Mixing the two would have resulted in one of the most common errors when displaying quantitative data: a mismatch of dimensions.

This problem is serious because your data would change linearly, while your representation would not. For example, for 5, 10, 20 people, the areas for circles with those radii are 19.6, 78.5, 314.15. The result would be visually misleading about a place's popularity. The moral is simple: don't lie about your data. Don't use snazzy effects, but especially if they end up in a faulty representation of data.

Adding Textual Information using JavaScript

We now have a lot of information in a graphic form that we wouldn't have if we'd chosen to use text only. But the text information is still necessary when we want to know things like the name of "that popular place on F and 6th". By using SVG's JavaScript bindings we can nicely include this information and avoid visual clutter, too. We will show the place's details only on mouse-overs. The following XSLT templates generates the necessary data and includes the JavaScript code.

Listing 10: Point Template with Comment Support

(full source)

<xsl:template name="point">

<!-- rest of the template as before in listing 8 -->

<xsl:param name="comment_title" />

<xsl:param name="comment_line1" />

<xsl:param name="comment_line2" />

<xsl:param name="comment_line3" />



<!-- comment box, initially hidden-->

<g id="{$gid}" style="visibility:hidden;z-index:10">

<rect stroke="black" fill="yellow" height="50" width="114" 

             x="{round($x * $x_proportion) + $x_skew + 16}"

     y="{round($y * $y_proportion) + $y_skew}"

                 ry="2" rx="2" 

     style="fill-opacity:0.6"/>

  <text style="font-family:Arial; font-size:9pt; font-weight:bold" 

            x="{round($x * $x_proportion) + $x_skew + 32}"

    y="{round($y * $y_proportion) + $y_skew + 10}">

        <tspan style="font-size:7pt; fill:#333333">

  <xsl:value-of select="$comment_title"/>

</tspan>

   </text>

<!-- same for comment lines  -->

</g>

<!-- rest of the template as before -->

</xsl:template>

As you can see, the first thing we do is insert four new parameters for the different comment lines we might want to pass to our point. These lines are composed in a small, semi-transparent rectangle with the text inside, grouped together with the g element. Note that the initial state of the group is invisible (set via the style attribute), Now we need a way to change that state, which is done using the simple JavaScript functions hideBox and showBox shown in Listing 11.

Listing 11: Javascript Functions showBox and hideBox

(full source)

<xsl:template name="jscripts">

<script language="Javascript">

<![CDATA[



/**   Show the textbox associated with targetID.

      evt: The event triggered. Included to easily deduce

      the owner document targetId: The Id of the g element

      to show. 

*/



function showBox(evt,targetId)

{

  var target = evt.getTarget();

  var svgdoc = target.getOwnerDocument();

  var svgobj = svgdoc.getElementById (targetId);

  if (svgobj)

  {    

    var parnode = svgobj.getParentNode();

    parnode.removeChild(svgobj); 

    parnode.appendChild(svgobj); 

     var svgstyle = svgobj.getStyle();

    if (svgstyle)

    svgstyle.setProperty ('visibility', 'visible');

  }    

}        



 /** hide box is just the same but the value of the property

  * is 'hidden'  */



]]>

 </script>

</xsl:template>

Even if you don't know JavaScript, the meaning of these functions is quite simple: set the style of an element (which we get by name) to "visible". The only rather weird factor about these functions is the fact that we reinsert the g node at the end of the document because SVG viewers paint the elements in the order in which they appear in the document. So we need to position it at the end to make sure it is not going to be obstructed by any others (if you are a CSS connoisseur thinking of z-index, that property is not supported.)

The only thing left is to associate the functions and the mouse over and mouse out events. This is really simple and involves only including onmouseover and onmouseout attributes on the image element. If you want to see the actual element, see the code here.

Two important additional lessons come from adding this text information. The first is XSLT-related: always bound your JavaScript code in CDATA blocks to avoid having to deal with special character (e.g. '<') escaping. The second is somewhat deeper: never guide your design by ease of programming. Your goal is to produce a valuable, efficient representation, so avoid solutions like modal messages and rely instead on less disruptive mechanisms like hovering information on-demand.

Now we finally have a complete representation of the city and its attractions (Figure 7) with all the advantages of text information plus the features, immediacy, and brevity only graphics provide.


Figure 7: Text Data Incorporated on Mouse Over

From Specific to General: Factorizing into Reusable Templates

We now have a nice way of creating semi-transparent points (with icons and hovering tool-tips) with an XSLT template. This is something we will want to reuse as we develop other graphics. The trick to creating a reusable template from a particular portion of a stylesheet is to reorganize the code so that all the necessary information is passed as parameters. Since we have been somewhat careful in the creation of our template and have tried to minimize the coupling of our point template, this refactorng is quite easy. All we really do is extract the template into another file and comment it properly so it can be easily reused.

Using our point library in other projects is extremely easy: include the library using xsl:call-template. Possible uses of the commented semi-transparent circle with an icon are endless. One such possible use that comes to mind is the tracking of fumigation plans on a crop field. I mention this agrarian example just to point out a use of the radius parameter to show information: the intensity of the fumigation does indeed have a correlation with the area covered, so we would not be lying by presenting area representations.

Summary and Conclusions

The use of XSLT and SVG opens up exciting new ground for the presentation of XML data on the Web. The correct use of these tools may improve vastly the quality and quantity of information your users can consume, as well as your process to present and create it. The creation of good visual representations of XML data using XSLT is governed by principles and best practices both on the programming and technical graphic design sides. In this article we have examined a few of them while providing an illustration of their implementation. The principles studied can be summarized in the following list. Naturally, this article is not exhaustive, but I hope it whets your appetite for the creation of useful graphic data using XML technologies.

Do Technique/Heuristic
Maximize space/information ratio The best graphics use fewer pixels to express more data
Create reusable graphic templates by induction Start with a prototype of what you want to do in plain SVG, then create a basic XSLT template, possibly tightly coupled with the rest of the stylesheet, finally, and only if it is general enough, factorize into a reusable library
Be truthful about your input data Provide representations that truthfully represent the nature and dimension of your input. Don't use n-dimensional representations for m-dimensional data (variations would be deceiving)
Use the possibilities of SVG to elegantly escape "flatland" Transparencies, JavaScript tool tips, and dynamic insertion of elements are great tools to allow several layers of information to coexist without cluttering. Using these tools is harder than overloading your graph or using disruptive mechanisms like alert boxes, but the extra effort on your part will be reflected on the quality and usefulness of your graphic and surely appreciated by your clients: elegance and effectiveness may sometimes be appreciated only subconsciously, but their absence is always noticed

 

Don't Technique/Heuristic
Don't decorate for the sake of decoration Your graph is a tool to convey condensed meaning. Anything other than truthful representation of your input data (unnecessary colors, distracting animations, background images of your favorite model) is garbage -- Tufte calls it "chart junk". A simple heuristic is to see the number of parameters of your XSLT template and the number of SVG shapes you generate. If you are generating gratuitous shapes, is time to consider a review.
Don't graph trivialities If your data set is small and/or acquiring and comparing the data is easier for the user on a text form, simply don't create a graphic. A simple table will do better. A useful technique is to enrich your XSLT stylesheets with xsl:if select="count(data) > X" elements to dynamically decide whether table or graphic would be better based on the number of data points.
Don't invent or suggest inexistent correlations Showing a correlation based on sound theory (like the relationship between the amount of fluid used and the area covered in crop spraying) may improve a graphic dramatically, but inventing a correlation based on a guess is a sure source of errors. Avoid it.

References

[1] The Visual Display of Quantitative Information Edward R. Tufte Graphics Press; 2nd Edition 07/2001
[2] Planet Orbit's representation from the Exoflight simulator, courtesy of Steven Hugg
[3] The Elements of Graphing Data By William S. Cleveland CRC Press, LLC; 03/1994;
[4] Envisioning Information Edward R. Tufte; Graphics Press; 10/1990
[5] Design, Form, and Chaos Pauld Rand; Yale University Press; 04 1993
[6] Design Dialogs Steven Heller, Elinor Pettit; 09 1998
[7] What is XLink? Fabio Arciniegas, xml.com 11 2000
[8] SVG 1.0 W3C Recommendation W3C 09 2001
[9] XPath 1.0 W3C Recommendation W3C 11 1999


For comments and questions, use the forum below or write to the author at FabioArciniegas@Postgraphy.com