Massimo Martinelli
massimo AT w3c.it, massimo.martinelli AT isti.cnr.it
Ufficio Italiano W3C, CNR-ISTI
Area della Ricerca CNR
via Moruzzi, 1
56124 Pisa
Corso AQUARIUS sulle Tecnologie Web
Firenze 16 Novembre 2010 - Pisa, 23 Novembre 2010
<xsl:template match="modello">
... trasformazione ...
</xsl:template>
<xsl:template match="nodo">
testo <tag> <xsl:value-of select="." /> </tag>
</xsl:template>
Se un nodo del documento XML combacia con quello della regola dell'esempio viene prodotto come risultato
testo <tag> valore (contenuto) dell'elemento corrente </tag>
Dato il seguente frammento XML
<nominativo>Mario Rossi</nominativo>
e il il seguente frammento XSLT
<xsl:template match="nominativo">
Nominativo: <strong><xsl:value-of select="."/></strong>
</xsl:template>
Risultato trasformazione:
Nominativo: <strong>Mario Rossi</strong>
Abbiamo visto che una regola di template specifica un nodo come sagoma
ma come si specificano i nodi ? ...
/Corsi/XSL/index.xml
<li>
quale oggetto nell'elenco, il 1°, o il 2°, ...)esempio: biblioteca/libro/titolo 3 passi separati dal carattere "/"
/
" /biblioteca/libro
/
" libro/titolo
asse::nodo di test [predicati] (zero o più predicati)
Documento XML
<?xml version="1.0" encoding="UTF-8" ?>
<saluto>
Benvenuto nel mondo di XSL-T
</saluto>
Documento XSL-T
<?xml version="1.0" encoding='UTF-8'?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head><title>Saluto</title></head>
<body>
<xsl:apply-templates select="saluto"/>
</body>
</html>
</xsl:template>
<xsl:template match="saluto">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
Associare lo stile aggiungendo nel file xml alla 2a riga
<?xml-stylesheet href="esempio3_documento.xsl" title="stile" type="text/xsl"?>
e aprire il file per esempio con Firefox e osservare con firebug oppure con Opera
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <-- aggiunta dal processore
<title>Saluto</title>
</head>
<body>
Benvenuto nel mondo di XSL-T
</body>
</html>
<xsl:template match="/">
<xsl:template match="x">
Nel successivo esempio vedremo questo template
<xsl:template match="n/x">
<xsl:apply-template select="x">
<xsl:value-of select=".">
Documento XML
<?xml version="1.0" encoding="UTF-8" ?>
<documento>
<autore>Mario Rossi</autore>
</documento>
Risultato della trasformazione
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Autore</title>
</head>
<body>Mario Rossi</body>
</html>
Documento XSL-T
<?xml version="1.0" encoding='UTF-8'?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head><title>Autore</title></head>
<body>
<xsl:apply-templates select="documento/autore"/>
</body>
</html>
</xsl:template>
<xsl:template match="autore">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
Documento XML
<?xml version="1.0" encoding="utf-8" ?>
<documento>
<autore>Mario Rossi</autore>
</documento>
Documento XSLT
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:template match="autore">
<div>Autore: <strong> <xsl:apply-templates /> </strong></div>
</xsl:template>
</xsl:stylesheet>
Applica i template relativi agli elementi figli (ove ve ne siano)
...e non solo...
./esempiCorso2010/esempio3_risultato.xml
<div>
Autore:
<strong>Mario Rossi</strong>
</div>
Attenzione: non funziona come ci aspetteremmo perché esistono delle regole predefinite...
<xsl:template match="nodo">
testo <tag> <xsl:apply-templates /> </tag>
</xsl:template>
testo <tag>
valore dell'elemento corrente <--regola di default
applicazione delle altre regole di template
</tag>
1. <xsl:template match="/ | *"> Applica le regole per qualsiasi elemento
<xsl:apply-templates/>
</xsl:template>
2. <xsl:template match="text()"> per qualsiasi testo
<xsl:value-of select="."/>
</xsl:template>
3. <xsl:template match="@*"> La regola per gli attributi è "ingannevole"
<xsl:value-of select="."/> Se non specifichiamo il template per gli attributi
</xsl:template> non vengono prodotti in output i valori
4. <xsl:template match="comment()"/> Non applicare le regole per i commenti
5. <xsl:template match="processing-instruction()"/> Ne per le istruzioni di processo
Dato il seguente file XML ...
<?xml version="1.0"?>
<biblioteca>
<libro codice="R415">
<titolo>Destinazione cervello</titolo>
<autore>
<cognome>Asimov</cognome>
<nome>Isaac</nome>
</autore>
<editore>Mondadori</editore>
<parola_chiave>romanzo</parola_chiave>
<parola_chiave>fantascienza</parola_chiave>
</libro>
<libro codice="N516">
<titolo>Sostiene Pereira</titolo>
<autore>
<cognome>Tabucchi</cognome>
<nome>Antonio</nome>
</autore>
<editore>Feltrinelli</editore>
<parola_chiave>romanzo</parola_chiave>
<parola_chiave>narrativa</parola_chiave>
</libro>
</biblioteca>
... e il seguente stylesheet minimale
<?xml version="1.0" encoding='UTF-8'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
</xsl:stylesheet>
il risultato della trasformazione:
<?xml version="1.0" encoding="UTF-8"?> <--Prologo XML Destinazione cervello Asimov Isaac Mondadori <-- contenuto degli elementi senza i relativi tag romanzo fantascienza Sostiene Pereira Tabucchi Antonio Feltrinelli <-- Attenzione agli spazi prodotti!!! romanzo Il secondo template di default ha narrativa prodotto in output anche gli spazi
<xsl:template match="nodo">
</xsl:template>
Non applica alcuna trasformazione per il nodo specificato
<xsl:template match="*|text()" />
Non applica alcuna per gli elementi e per i testi (a meno di regole più specifiche)
<xsl:output method="xml"/>
<xsl:output method="html"/>
<xsl:output method="text"/>
<xsl:output indent="yes"/>
<xsl:output doctype-system="nomefile.dtd"/>
<!DOCTYPE elementoradice SYSTEM "nomefile.dtd">
<xsl:apply-templates/>
<xsl:apply-templates select="nodo" />
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"
doctype-public="-//W3C//DTD XHTML 1.1//EN"
doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"/>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>esempio di output XHTML</title>
</head>
<body>
<xsl:apply-templates />
</body>
</html>
</xsl:template>
...
</xsl:stylesheet>
Dato il seguente documento XML:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="brani.xsl" title="stile" type="text/xsl"?>
<brani>
<brano id="5">
<titolo>Asturias</titolo>
<autore>Andres Segovia</autore>
<incisione>Deutsche Grammophon</incisione>
</brano>
</brani>
Trasformare in XHTML 1 (strict) in modo da produrre questo risultato:
Titolo brano: Asturias
Identificatore: 5
Incisione: Deutsche Grammophon
La priorità di default è determinata come segue:
*
" non qualificato ha priorità -0.5Esempi
elemento
", "html:p
", e "@attributo
" hanno priorità 0html:*
" ha priorità -0.25*
" ha priorita -0.5elemento1/elemento2
" ha priorità 0.5elemento[@attributo]
" ha priorità 0.5<xsl:if test="$condizione">
questo messaggio apparirà solo se $condizione è true
</xsl:if>
<xsl:if test="nome">
esiste l'elemento "nome", figlio dell'elemento corrente ?<xsl:if test="count(x)>1">
esiste più di un elemento "x" figlio dell'elemento corrente ?<xsl:if test="$x">
il valore della variabile "x" è true ?Dividiamo gli autori con una virgola:
<xsl:template match="autore">
<xsl:value-of select="./cognome" />
<xsl:text> </xsl:text>
<xsl:value-of select="./nome" />
<xsl:apply-templates />
<xsl:if test="not(position()=last())">, </xsl:if>
</xsl:template>
^
<xsl:variable name="var" expr="subelement[position() mod 3]"/>
* Notare la dichiarazione di una variabile il cui valore è una espressione matematica
<xsl:variable name="persona">
<xsl:if test="$nome">...</xsl:if>
</xsl:variable>
<xsl:template match="film">
<h1> elenco dvd</h1>
<table>
<xsl:apply-templates select="dvd"/>
</table>
<h1> elenco videocassette</h1>
<table>
<xsl:apply-templates select="cassetta"/>
</table>
</xsl:template>
Supponiamo di dover gestire la prenotazione di lezioni che possono essere di gruppo o individuali
<xsl:template match="lezione">
<h3><xsl:value-of select="titoloLezione"/></h3>
<h4>Aula: <xsl:value-of select="../../@name"/></h4>
<h4>Prenotata da : <xsl:value-of select='prenotataDa'/></h4>
<h4>Allievi:</h4>
<xsl:for-each select='allievi'>
<xsl:choose>
<xsl:when test="gruppo"> <-- Esiste un elemento gruppo figlio dell'elemento corrente ?
  Gruppo: <em><xsl:value-of select="gruppo"/></em><br />
</xsl:when>
<xsl:otherwise>
  <xsl:value-of select="individuo"/><br />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<p> dalle ore <xsl:value-of select="oriario/da"/>
alle ore <xsl:value-of select="orario/alle"/></p>
. . .
</xsl:template>
  ==
<xsl:template match="elemento">
<xsl:variable name="var" expr="sottoelemento[position() mod 3]"/>
<xsl:choose>
<xsl:when test='$var=1'>
... fai qualcosa...
</xsl:when>
<xsl:when test='$var=2'>
... fai un'altra cosa ...
</xsl:when>
<xsl:otherwise>
... fai qualcosaltro ...
</xsl:otherwise>
</xsl:choose>
<xsl:apply-templates/>
</xsl:template>
Modificare l'ordine dei libri per autore
<xsl:template match="biblioteca"> <xsl:apply-templates select="libro[code >= 'M']" > <xsl:sort select="libro/autore/cognome" />
Ordina per cognome<xsl:sort select="libro//nome" />
poi per nome</xsl:apply-templates> </xsl:template>
Supponendo di voler modificare l'ordine per prezzo (numerico)
<xsl:sort select="libro/prezzo" order="descending"
Specifica l'ordine discendente (per difetto = ascending)data-type="number" />
Specifica il tipo di dato (per difetto = text)
<xsl:element name="nome_elemento">
Crea un elemento <nome_elemento> e lo restituisce in uscita
<xsl:element name="cognome">
<xsl:value-of select=".">
</xsl:element>
Crea un elemento <cognome>
contenente il valore dell'elemento corrente
<xsl:attribute name="nome_attributo">
Crea un attributo nome_attributo su <xsl:element>
corrente.
Il contenuto di <xsl:attribute>
diventa il valore dell'attributo creato
<indirizzo_sito_web>http://www.cnr.it</indirizzo_sito_web>
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="indirizzo_sito_web">
</xsl:attribute>
il sito web del CNR
</xsl:element>
<a href="http://www.cnr.it">il sito web del CNR</a>
XSL-T permette di invocare una regola template con passaggio di parametri
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="nome" /> // parametro con visibilità globale
<xsl:template name="calcoloArea">
<xsl:param name="larghezza" />
<xsl:param name="altezza" />
<xsl:value-of select="$larghezza * $altezza" />
</xsl:template>
<xsl:call-template name="calcolaArea"> // invoca il template
<xsl:with-param name="larghezza" select="10" /> // passaggio di parametro
<xsl:with-param name="altezza" select="20" /> // passaggio di parametro
</xsl:call-template>
</xsl:stylesheet>
I template si possono invocare ricorsivamente (call template all'interno dello stesso template che chiama)
Un ottimo esempio è il template Somma riportato nel capitolo 7 sezione 2 del libro "XSL-T" O'Reilly
http://oreilly.com/catalog/orxmlapp/chapter/ch07.html
Un foglio di stile può elaborare più di un documento XML caricando altri documenti con la funzione document()
prodotti.xml
<?xml version="1.0"?>
<prodotti>
<prodotto>
<nome>Monitor<nome>
<prezzo valuta="eu">900</prezzo>
<descrizione>Display LCD ... </descrizione>
</prodotto>
...
</prodotti>
valute.xml
<?xml version="1.0"?>
<valute>
<valuta>
<codice>eu<codice>
<nome>Euro<nome>
</valuta>
...
</valute>
...
<xsl:variable
nome=valute
select="document(valute.xml)/valute" />
...
<xsl:template match="prodotto">
<xsl:variable name="valuta" select="prezzo/@valuta" />
<xsl:value-of select="prezzo" />
<xsl:value-of select="$valute/valuta[codice="$valuta"]/nome" />
<xsl:value-of select="descrizione" />
</xsl:template>
Analizziamo gli esempi iniziali
trasformazione di un stesso documento XML in SVG, HTML e PDF
Domande?
Se non è sul Web non esiste ...
... troverete le slide all'indirizzo http://www.w3c.it/projects/aquarius/presentazioni/moduloD/xml/indexConsegnare.html e http://www1.isti.cnr.it/~Martinelli/XML/doc/TecnologieWeb/xsl/index.html