Anglais Francais Prosygma Italie
-
    hebergement asp
prosygma_logo

Transformer un document XML en SVG avec XSLT

Techniques

Cette section permet de regrouper un ensemble de techniques ou de scripts qui ont l'originalité d'arriver à résoudre une difficulté avec le moindre effort ou qui sont particulièrement efficaces...


Techniques/ Transformer un document XML en SVG avec XSLT

La technique XML est trés avantageuse car elle permet de disposer d'une source de données complètement indépendante de la représentation qu'on pourra leur donner. Utilisé conjointement avec XSLT nous pouvons ainsi transformer une fichier XML en des sorties variées et adaptées au média visé comme le format (X)HTML, PDF, RTF, SVG, SMIL...

Dans cet article je vais essayer de vous montrer un exemple simple de transformation d'un document XML en graphique SVG en opérant une transformation depuis ASP. La rédaction d'un fichier XML,XSL,SVG est sensée être connue. ( Des cours adéquats seront bientôt créés à cet effet.)

C'est la dll MSXML qui nous permettra d'opérer la transformation à la volée. Le graphique généré sera ensuite directement affichable sur le poste client grâce au plug-in ADOBE SVG Viewer disponible à cette adresse : http://www.adobe.com/svg/viewer/install/main.html. Le langage SVG est lui même une grammaire XML permettant la représentation de graphiques vectoriels plus ou moins complexes. .

Celui-ci pourra bien évidemment provenir d'une base de données, être stocké dans le système de fichier ou provenir d'un flux depuis un site externe ... Dans notre cas précis, il sera enregistré sur le disque du serveur pour des raisons de simplifications.

Sales.xml

<?xml version="1.0" encoding="iso-8859-1" ?>
<Sales>
   <Report Year="2002">
      <Summary Region="North">
         <Q1 TotalSales="10" />
         <Q2 TotalSales="150" />
         <Q3 TotalSales="140" />
         <Q4 TotalSales="180" />
      </Summary>
      <Summary Region="East">
         <Q1 TotalSales="110" />
         <Q2 TotalSales="70" />
         <Q3 TotalSales="100" />
         <Q4 TotalSales="50" />
      </Summary>
      <Summary Region="West">
         <Q1 TotalSales="60" />
         <Q2 TotalSales="140" />
         <Q3 TotalSales="130" />
         <Q4 TotalSales="200" />
      </Summary>
      <Summary Region="South">
         <Q1 TotalSales="100" />
         <Q2 TotalSales="140" />
         <Q3 TotalSales="80" />
         <Q4 TotalSales="95" />
      </Summary>
   </Report>
</Sales>
        

De même celui-ci, est normalement stocké au même endroit :

Sales.xsl

<?xml version="1.0" encoding="iso-8859-1"?> 
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" media-type="image/svg+xml"
   encoding="iso-8859-1" indent="yes" /> 
 <xsl:strip-space elements="*" />

 <xsl:template match="/">
 <svg width="14cm" height="10cm" 
 xmlns="http://www.w3.org/2000/svg">
 <!--Heading-->
 <text x="5" y="28" text-anchor="left" 
 font-weight="bolder" font-size="20" fill="maroon" 
 text-decoration="underline">
 Sales Report for DP & Co. 
 Year <xsl:value-of select="/Sales/Report/@Year"/>
 </text>

 <!--Caption (Vertical)-->
 <g transform="translate(40, 100) rotate(270, 0, 0)">
 <text x="-98" y="5" text-anchor="middle" 
 font-weight="bolder" font-size="16" fill="black">
 Sales (Hundred Thousand USD)
 </text>
 </g>

 <!--Caption (Horizontal)-->
 <text x="190" y="350" font-size="16" 
 font-weight="bolder" fill="black">
 Region (Per Quarter)
 </text>

 <!--Lines-->
 <g stroke="gray" stroke-width="1">
 <line x1="70" y1="300" x2="490" y2="300"/>
 <line x1="70" y1="300" x2="70" y2="70"/>
 </g>
 
 <!--Data Charts-->
 <xsl:call-template name="drawSalesBars">
 <xsl:with-param name="Region" select="string('North')"/>
 <xsl:with-param name="barColor" select="string('#B8CCDE')"/>
 <xsl:with-param name="startXPosition" select="80"/>
 </xsl:call-template>

 <xsl:call-template name="drawSalesBars">
 <xsl:with-param name="Region" select="string('East')"/>
 <xsl:with-param name="barColor" select="string('#FFFFCC')"/>
 <xsl:with-param name="startXPosition" select="180"/>
 </xsl:call-template>

 <xsl:call-template name="drawSalesBars">
 <xsl:with-param name="Region" select="string('West')"/>
 <xsl:with-param name="barColor" select="string('#9999FF')"/>
 <xsl:with-param name="startXPosition" select="280"/>
 </xsl:call-template>

 <xsl:call-template name="drawSalesBars">
 <xsl:with-param name="Region" select="string('South')"/>
 <xsl:with-param name="barColor" select="string('#993366')"/>
 <xsl:with-param name="startXPosition" select="380"/>
 </xsl:call-template>
 </svg>
</xsl:template>
  
<xsl:template name="drawSalesBars" 
xmlns="http://www.w3.org/2000/svg">
<xsl:param name="Region"/>
<xsl:param name="barColor"/>
<xsl:param name="startXPosition"/>
    
<text x="{$startXPosition+10}" y="320" 
font-weight="bolder" font-size="16" fill="#225C91">
<xsl:value-of select="$Region" />
</text>
    
<xsl:variable name="q1SalesAmt" 
select="/Sales/Report/Summary[@Region=$Region]/
	Q1/@TotalSales"/>
 <xsl:variable 
 name="q1YPos" select="300 - $q1SalesAmt" />
 <rect stroke-width="1" stroke="black" width="15" 
 fill="{$barColor}" x="{$startXPosition}"
 y="{$q1YPos}" height="{$q1SalesAmt}"/>
 <text x="{$startXPosition}" y="{$q1YPos - 5}"
 font-size="11" fill="black"><xsl:value-of 
 select="$q1SalesAmt"/></text>

 <xsl:variable name="q2SalesAmt" 
select="/Sales/Report/Summary[@Region=$Region]/
	Q2/@TotalSales"/>
 <xsl:variable 
 name="q2YPos" select="300 - $q2SalesAmt" />
 <rect stroke-width="1" stroke="black" width="15" 
 fill="{$barColor}" x="{$startXPosition + 20}" 
 y="{$q2YPos}" height="{$q2SalesAmt}"/>
 <text x="{$startXPosition + 20}" y="{$q2YPos - 5}"
 font-size="11" 
 	fill="black"><xsl:value-of 
 	select="$q2SalesAmt"/>
 </text>
 <xsl:variable name="q3SalesAmt" 
select="/Sales/Report/Summary[@Region=$Region]/
	Q3/@TotalSales" />
 <xsl:variable 
 	name="q3YPos" 
 	select="300 - $q3SalesAmt" />
 <rect 
 	stroke-width="1" 
 	stroke="black" 
 	width="15" 
 fill="{$barColor}" 
 x="{$startXPosition + 40}" 
 y="{$q3YPos}" 
 height="{$q3SalesAmt}"/>
 <text 
 	x="{$startXPosition + 40}" y="{$q3YPos - 5}"
 	font-size="11" 
 	fill="black"><xsl:value-of 
 	select="$q3SalesAmt"/>
 </text>

 <xsl:variable name="q4SalesAmt" 
select="/Sales/Report/Summary[@Region=$Region]/
	Q4/@TotalSales"/>
 <xsl:variable 
 	name="q4YPos" 
 	select="300 - $q4SalesAmt" />
<rect stroke-width="1" stroke="black" width="15" 
 fill="{$barColor}" x="{$startXPosition + 60}" 
 y="{$q4YPos}" height="{$q4SalesAmt}"/>
 <text x="{$startXPosition + 60}" y="{$q4YPos - 5}"
 font-size="11" 
 	fill="black"><xsl:value-of 
 	select="$q4SalesAmt"/>
 </text>
</xsl:template>
</xsl:stylesheet>

Les fichiers sources et de transformation étant créés nous pouvoins enfin nous pencher sur le fichier ASP :

Sales.asp


<%
response.buffer = true
set xml = Server.CreateObject("Microsoft.XMLDOM")
xml.async = false
xml.load(Server.MapPath("sales.xml"))

set xsl = Server.CreateObject("Microsoft.XMLDOM")
xsl.async = false
xsl.load(Server.MapPath("sales.xsl"))
response.Charset="iso-8859-1"
response.contenttype = "image/svg+xml"
xml.transformNodeToObject xsl,Response
%>



Afin de tranformer le fichier XML en SVG, c'est la méthode transformNodeToObject que j'ai employé au lieu de transformNode qui nous contraindrait à toujours garder l'encodage UTF-16 et ce malgré la mention <xsl:output encoding="..."/> utilisée. La méthode transformNodeToObject nous permet de générer un objet Stream qui ne nous pose aucun problème d'encodage et que nous pouvons donc renvoyer vers l'objet Response afin de permettre la sortie du SVG sur le poste client.