Imparate a programmare XML in un'ora usando SVG!


Prima di cominciare una breve precisazione. Xml non e' un linguaggio di programmazione e quindi non si puo' programmare XML! Inoltre in un'ora e' impossibile imparare a programmare in qualsiasi linguaggio! E allora? Xml permette di definire dei linguaggi di marcatura (tipo html per intenderci) e noi useremo 2 di questi linguaggi :SVG e XSL che assieme a Javascript sono un modo davvero affascinante di imparare a cosa serve l'XML. Se poi voi siete gia' programmatori esperti di altri linguaggi allora solo guardando le figure imparerete a programmare xml in un'ora. Se oltre le figure volete vedere le immagini SVG in tutta la loro bellezza, allora procuratevi un browser che capisce SVG e cliccate sui link : guardate qui l'immagine svg.
Il nostro primo elemento : un cerchio guarda l'immagine svg


<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="600" viewBox="0 0 400 300">
<circle cx="50" cy="20" r="10" stroke="red" stroke-width="2" fill="yellow" />
</svg>
SVG (Scalable Vector Graphics) e' un linguaggio di marcatura definito da W3C. Dalla documentazione ufficiale vediamo che esistono oltre al cerchio altri elementi che rappresentano forme:rect, ellipse, line, polyline, polygon. Ma sono tutti casi particolari di un elemento path che permette di definire forme generiche in maniera molto compatta.
Un triangolo in un rettangolo guarda l'immagine svg
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="600" viewBox="0 0 400 300">
<rect x="1" y="1" width="50" height="40" fill="none" stroke="green" />
<path d="M 10 10 L 40 10 L 25 30 z" fill="yellow" stroke="black" stroke-width="3" />
</svg>

Un esagono guarda l'immagine svg
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="600" viewBox="-200 -200  400 300">
<rect x="1" y="1" width="50" height="50" fill="none" stroke="green" />
<line x1="10" y1="5" x2="40" y2="5" stroke="red" stroke-width="3" />
<line x1="10" y1="5" x2="40" y2="5" stroke="red" stroke-width="3" transform="rotate(60,25,25)" />
<line x1="10" y1="5" x2="40" y2="5" stroke="red" stroke-width="3" transform="rotate(120,25,25)" />
<line x1="10" y1="5" x2="40" y2="5" stroke="red" stroke-width="3" transform="rotate(180,25,25)" />
<line x1="10" y1="5" x2="40" y2="5" stroke="red" stroke-width="3" transform="rotate(240,25,25)" />
<line x1="10" y1="5" x2="40" y2="5" stroke="red" stroke-width="3" transform="rotate(300,25,25)" />

</svg>

Esagoni : raggruppamento e riuso guarda l'immagine svg
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="800" height="600" viewBox=" 0 0 400 300 ">
<defs>
<g id="esagono">
<line x1="10" y1="5" x2="40" y2="5" stroke="red" stroke-width="3" />
<line x1="10" y1="5" x2="40" y2="5" stroke="red" stroke-width="3" transform="rotate(60,25,25)" />
<line x1="10" y1="5" x2="40" y2="5" stroke="red" stroke-width="3" transform="rotate(120,25,25)" />
<line x1="10" y1="5" x2="40" y2="5" stroke="red" stroke-width="3" transform="rotate(180,25,25)" />
<line x1="10" y1="5" x2="40" y2="5" stroke="red" stroke-width="3" transform="rotate(240,25,25)" />
<line x1="10" y1="5" x2="40" y2="5" stroke="red" stroke-width="3" transform="rotate(300,25,25)" />
</g>
</defs>
<rect x="1" y="1" width="500" height="50" fill="none" stroke="green" />
<use xlink:href="#esagono" />
<use xlink:href="#esagono" transform="translate(60) scale(0.5)" />
<use xlink:href="#esagono" transform="translate(80,25) scale(0.5)" />
<use xlink:href="#esagono" transform="translate(110,25) scale(0.3) " />
<use xlink:href="#esagono" transform="matrix(.9 .3 .3 .8 130 10) scale(0.5)" />
<use xlink:href="#esagono" transform="matrix(.9 .3 .8 .7 150 10) scale(0.5)" />
</svg>


Spirale di quadrati guarda l'immagine svg
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"  viewBox="-40 -40 80 80">
<defs>
<linearGradient id="gradient" gradientUnits="userSpaceOnUse" x1="-100" y1="-100" x2="100" y2="100">
<stop offset="0" stop-color="yellow"/>
<stop offset="1" stop-color="magenta"/></linearGradient>
</defs>
<rect x="-100" y="-100" width="200" height="200" fill="url(#gradient)" stroke="black"/>
<g transform="scale(.8, .8) rotate(5)"><rect x="-100" y="-100" width="200" height="200" fill="url(#gradient)" stroke="black"/>
<g transform="scale(.8, .8) rotate(5)"><rect x="-100" y="-100" width="200" height="200" fill="url(#gradient)" stroke="black"/>
  ...
  Inserire qui un numero qualsiasi di ripetizioni dello stesso elemento 
  ...
</g>
</g>
</svg>

Animazioni, testi, immagini guarda l'immagine svg
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"  viewBox="0 0 400 400">
<text id="start" x="10" y="50">Clicca</text>
<g id="pluto" transform="rotate(0,50,95)">
<text x="30" y="90">Ciao a Tutti
<animateTransform  attributeName="transform" type="rotate" from="0 50 95" to="360 50 95" begin="start.click" dur="5s" />
</text>
</g>
<g id="paperino" transform="rotate(30,125,100)">
<image x="100" y="75" width="50" height="50" xlink:href="srunning.gif" opacity="0.5">
<animateTransform  attributeName="transform" type="rotate" from="30 125 100" to="360 125 100" begin="start.click" dur="5s" />

</image>
</g>
<rect id="pippo" x="10"  y="50"  width="150" height="75" fill="aqua" >
<animate  attributeType="CSS" attributeName="opacity"  from="1" to="0" begin="start.click" dur="5s"  />
<animateColor  attributeType="CSS" attributeName="fill"  from="aqua" to="magenta" begin="start.click" dur="5s"  />
</rect>

</svg>

Interattivita' senza e con Javascript guarda l'immagine svg senza Javascript, con Javascript

file inter.svg
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns"http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"  viewBox="0 0 400 400">
<text id="start" x="10" y="50">Clicca sul rettangolo rosso</text>
<rect id="pippo" x="10"  y="50"  width="150" height="75" fill="red" >
<set attributeName="fill" from="red" to="yellow" begin="click" />
<set attributeName="fill"  to="red" begin="mouseout" />
 </rect>
</svg>
file inter1.svg
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns"http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"  viewBox="0 0 400 400">
<script type="text/javascript">
<![CDATA[
function changeCol(evt,color)
{
   var rettangolo = evt.getTarget();
   rettangolo.setAttribute("fill",
         color);

}
// ]]>
</script>
<text id="start" x="10" y="50">Clicca sul rettangolo rosso</text>
<rect id="pippo" x="10"  y="50"  width="150" height="75" fill="red"
onclick="changeCol(evt,'yellow')" onmouseout="changeCol(evt,'red')" >
 </rect>
</svg>

Generazione di un'immagine a caso guarda l'immagine svg ,immagine e programma originale Java

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"  viewBox="0 0 1024 1024" onload="disegna(evt)" >
<script type="text/javascript">
<![CDATA[
function disegna(evt)
{
   var max = 1000;
   var redVal=0;
   var greenVal=0;
   var blueVal=0;
   var prevx = 512.;
   var prevy = 512.;
   var x = 0.;
   var y = 0.;
   var dis = 10;
   var an = 0;
   var c1 = Math.random()*1000;
   var inter = 5;
   var targ = evt.getTarget();
   svgdoc = targ.getOwnerDocument();
   spirale = svgdoc.getElementById('spirale');
   dval = "M 512 512";
    for (var i=0; i<=max; i++)
                 {
         x = prevx + dis * Math.sin(an);
         y = prevy + dis * Math.cos(an); 
         if(x > 1024) break;
         if(x < 1) break;
         if(y > 1024) break;
         if(y < 1) break;
         x1 = Math.round(x);
         y1 = Math.round(y);
         dval = dval + "L "+ x1 + " " + y1+" ";
         prevx = x;
         prevy = y;
         dis = dis + inter;
         an = an + c1;
        }
  // dval = dval+" z";
   spirale.setAttribute("d", dval);
   redVal = Math.round(Math.random()*255);
   greenVal = Math.round(Math.random()*255);
   blueVal = Math.round(Math.random()*255);
   spirale.setAttribute("fill","rgb(" + redVal + "," + greenVal + "," + blueVal + ")");
   redVal = Math.round(Math.random()*255);
   greenVal = Math.round(Math.random()*255);
   blueVal = Math.round(Math.random()*255);
   spirale.setAttribute("stroke","rgb(" + redVal + "," + greenVal + "," + blueVal + ")");
}
// ]]>
</script>
<rect x="1" y="1" width="1024" height="1024" fill="none" stroke="green" />
<path id="spirale"  d="M 10 10 L 40 10 L 25 30 z" fill="yellow" stroke="black" stroke-width="3" />
</svg>

Generazione di una spirale di immagini guarda l'immagine svg ,Genera tu stesso la spirale con una tua immagine!


<?
header("Content-type: image/svg+xml");
print('<?xml version="1.0" encoding="UTF-8"?>');
print('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"  viewBox="-100 -100 200 200">');
print('<defs>');
print('<g id="immagine">');
print("<image x=\"-100\" y=\"-100\" width=\"200\" height=\"100\" xlink:href=\"$url\" opacity=\"$opacita\"/>");
print('</g> </defs>');
if($nripetizioni < 1) $nripetizioni= 1;
if($nripetizioni > 100) $nripetizioni= 100;
for ($i = 0; $i < $nripetizioni; $i+=1) {
print("<g transform=\"scale($riduzione,$riduzione) rotate($rotazione,0,0)\"><use xlink:href=\"#immagine\"/>\n"); 
}
for ($i = 0; $i < $nripetizioni; $i+=1) {
print('</g>'); 
}
print('</svg>');
?>

Generazione di rettangoli a caso clicca sul rettangolo blu piu' volte! (firefox version)


<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewbox= "0 0 600 400" > 
<script type="text/ecmascript">
<![CDATA[ 
function addrect(evt) { 
var svgobj=evt.target; 
var svgdoc = svgobj.getOwnerDocument(); 
var newnode = svgobj.cloneNode(false); 
svgstyle = newnode.getStyle(); 
var x = 10+480*Math.random(); var y = 10+330*Math.random(); var width = 10+200*Math.random(); var height = 10+100*Math.random(); 
var red = Math.round(Math.random()*255);
var green = Math.round(Math.random()*255);
var blue = Math.round(Math.random()*255);
svgstyle.setProperty ('opacity', Math.random()); 
svgstyle.setProperty ('fill',"rgb(" + red + "," + green+ "," + blue + ")" ); 
newnode.setAttribute ('x', x); newnode.setAttribute ('y', y); 
newnode.setAttribute ('width', width); 
newnode.setAttribute ('height', height); 
var contents = svgdoc.getElementById ('quadrato'); 
newnode = contents.appendChild (newnode); } ]]>
</script> 
<rect x="1" y="1" style="fill:#bbffbb" width="598" height="398"/> 
<g id="quadrato"> 
<rect onclick="addrect(evt)" style="fill:blue;opacity:1" x="250" y="100" width="20" height="20" /> 
</g> 
</svg>

Trasformare dei dati in un grafico Grafico ottenuto da questi dati.

<?xml version="1.0"?>
<!-- stylesheet.xsl -->
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" indent="yes"
  media-type="image/svg+xml"/>

  <xsl:template match="dati">
    <svg width="400" height="400">
     <g id="mese" transform="translate(0,200)">
     <xsl:for-each select="mese">
     <xsl:variable name="valore" select="valore"/> 
     <text x="{position()*25 + 7.5}" y="0" style="font-family:arial;text-anchor:middle;baseline-shift:-15;">
     <xsl:value-of select="nome"/>
     </text>
<rect x="{position()*25}" y="-{$valore*1.5}" height="{$valore*1.5}" width="15" style="fill:red"/>
     </xsl:for-each>
    </g>
    </svg>
  </xsl:template>

</xsl:stylesheet>
Se volete provare voi stessi questo esempio scaricatevi il file di dati e il cosiddetto foglio di stile xsl. Come macchina per fare la trasformazione potete utilizzare questo programma java. Date il comando:
java trasforma dati1.xsl dati1.xml > dati1.svg
e il diagramma e' fatto!
Bibliografia
  1. KevLinDev Tutorials
  2. SVG short programs
  3. SVG@Tecfa

INDIETRO a Seminario su Xml
Maintained by :info@zitogiuseppe.com Last modified: