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>
- Ogni xml comincia allo stesso modo con la riga
<?xml version="1.0" encoding="UTF-8"?>
- Ogni xml ha un nodo radice che racchiude tutti gli altri nodi. In
questo caso
svg
- Questo nodo radice ha tra gli attributi xmlns che definisce il
namespace o vocabolario usato.
- Un elemento corrisponde alla marcatura iniziale + quella finale.
Se tra i 2 non c'e' niente possiamo abbreviare la scrittura usando lo "/"
alla fine della marcatura iniziale. In questo caso l'elemento circle
di SVG ha diversi attributi che permettono di definire
varie caratteristiche del cerchio.
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>
- tra gli eventi che e' possibile usare per far partire animazioni
o altro abbiamo
click
, mouseover,mousemove,mouseout,accessKey(key),...
- notate come sia possibile fare riferimento all'evento generato da un'altro
oggetto scrivendo
nomeoggetto.nomeevento
- il comando
animate
(come altri comandi SVG) sono stati "riciclati" da SMIL un linguaggio di marcatura per fare presentazioni multimediali.
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>
- Il comando
set
permette di aggiungere interattivita' cambiando
qualche attributo quando succede un certo evento
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>
- Questo disegno si comporta esattamente come il precedente ma il tutto
e' ottenuto con un programma Javascript o per essere precisi ECMAScript.
- Il programma viene incluso in un nodo
script
e puo'
accedere all'albero XML modificandolo (aggiungere nodi,eliminare
nodi, modificare attributi di nodi gia' esistenti).
- Il programma viene aggiunto come un elemento di tipo
CDATA
.
Una sezione CDATA viene usata
per permettere l'inclusione di caratteri come le parentesi angolari che potrebbero trarre in inganno il parser.
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>');
?>
- Qui volevamo rendere l'immagine configurabile a piacere. Purtroppo SVG
non ha ancora gli oggetti grafici necessari. Per generare l'immagine avremmo
dovuto ricorrere all'html e ai form : cosa sconsigliata e che non funziona
molto bene.(In SVG 1.2 la cosa cambiera' ed avremo la possibilita' di usare
tutta una serie di oggetti grafici presi per lo piu' dalla specifica XForms).
Invece uno script PHP eseguito dal server puo' fare il tutto
in maniera molto semplice.
- PHP usa i valori impostati nel modulo per generare il codice xml
personalizzato.PHP non fa che inviare un file di testo.
- La prima istruzione:
header("Content-type: image/svg+xml");
serve a informare il
browser che sta arrivando un'immagine svg.
- Questa tecnica puo' essere usata anche con ASP e JSP
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>
- Javascript viene usato questa volta per aggiungere nuovi nodi all'albero
del documento.
- il metodo
cloneNode
ci permette di partire da un nodo vuoto
che riempiamo con le sue proprieta' di stile e attributi e alla fine attacchiamo come figlio del nodo contenitore quadrato
.
- Notate il metodo di rendering di SVG detto del pittore in cui
i nuovi rettangoli sono disegnati sopra i vecchi rettangoli e a seconda dell'opacita' possono creare nuovi colori dovuti alla somma dei colori sovrapposti.
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!
- Ecco un primo semplicissimo esempio di uso del linguaggio XSLT per trasformare un xml in un'altro
xml.
- Potete modificare il file xml dei dati e ottenere una figura svg che rispecchia i nuovi dati.
- Potete modificare il modo di rappresentare i dati cambiando il file xsl:ad esempio dimensione
e colore delle barre.
- La specifica
output
all'inizio indica il tipo di trasformazione da fare.
- XSLT e' un dialetto xml che e' anche un vero e proprio linguaggio di programmazione, anche
se di tipo particolare.
- Esso si basa infatti su una serie di regole di trasformazioni definite dal comando
template
.
- In queso caso abbiamo un'unica regola applicata al nodo
dati
- In questa regola si specifica di fare un ciclo
for-each
da ripetere per
tutti i nodi mese
.
- Notate la definizione di variabile (comando
variable
) e la sua assegnazione col contenuto
di un particolare nodo del file di dati. Questa viene usata in seguito scrivendo $nome_variabile.
- Il comando
value-of
permette di trasferire una quantita' dal file xml al
file svg senza cambiamenti.
Bibliografia
- KevLinDev Tutorials
- SVG short programs
- SVG@Tecfa
INDIETRO a Seminario su Xml
Maintained by Zito Giuseppe:info@zitogiuseppe.com
Last modified: