XSLT Trasformazioni XSL Ing. Luca Sabatucci XSLT Uno dei vantaggi principali nell'utilizzo dell'Extensible Markup Language è la facilità con cui si possono trasformare i documenti di dati XML in altri formati e strutture, come i file HyperText Markup Language (HTML). Lo strumento utilizzato per definire queste trasformazioni è denominato Extensible Stylesheet Language Transformations (XSLT). Foglio di stile Un insieme di regole che permettono di trasformare un documento in un altro documento si chiama foglio di stile Un foglio di stile si definisce mediante l’XSL XSL è una applicazione XML Processo di trasformazione La trasformazione avviene tramite un processore chiamato elaboratore XSLT Applicazioni pratiche Web Un documento XML può essere trasformato in una pagina HTML in modo da essere visualizzato tramite browser Web XSL-FO Un documento può essere trasformato in formato FO (Formatting Object) che rappresenta una applicazione di formattazione precisa dei documenti narrativi Namespace XSL XSL è una applicazione XML XSL definisce un proprio DTD e un Namespace L’URL da usare per il namespace è xmlns:xsl="http://www.w3.org/1999/XSL/Transform" Il namespace viene generalmente associato al prefisso ‘xsl’ xsl:stylesheet L’elemento radice di un documento XSL è xsl:stylesheet All’interno dell’elemento xsl:stylesheet si mettono le regole di trasformazione Il più semplice foglio di stile XSL prevede che non vi siano regole di trasformazione Catalogo persone <catalogo> <persona> <nome>Luca</nome> <cognome>Sabatucci</cognome> <origine> <data_di_nascita> <giorno>16</giorno> <mese>2</mese> <anno>1976</anno> </data_di_nascita> <luogo_di_nascita>Palermo</luogo_di_nascita> </origine> <professione da="Luglio 2002">Ingegnere</professione> </persona> <persona> <nome>Mario</nome> <cognome>Rossi</cognome> <origine> <data_di_nascita> <giorno>4</giorno> <mese>7</mese> <anno>1982</anno> … La più semplice trasformazione Se si trasforma il file XML catalogo persone con un foglio di stile vuoto, come quello mostrato di seguito… <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/> Output Si ottiene l’output mostrato di seguito: LucaSabatucci1621976PalermoIngegnere MarioRossi471982Milano Foglio di stile vuoto In assenza di regole la trasformazione è la seguente: Viene prelevato il testo interno agli elementi del documento di input Viene quindi riprodotto il contenuto ma non il markup. In questo caso il risultato non è un documento XML Modelli e regole Per controllare il modo in cui viene generato l’output in base all’input bisogna aggiungere dei modelli all’interno del foglio di stile Ogni modello è rappresentato da un elemento xsl:template, dotato di un attributo match xsl:template definisce una regola di trasformazione match identifica il tipo di input che attiva la regola esempio: persona “Una persona” Esempio Di seguito viene mostrata la regola corrispondente a: persona “Una persona” <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="persona">Una persona</xsl:template> </xsl:stylesheet> Output: Una personaUna persona Associamo uno stile HTML E’ possibile fare in modo che l’output sia un documento XML ben formato <xsl:stylesheet version="1.0" xmlns:xsl=“…"> <xsl:template match="persona"> <p>Una persona</p> </xsl:template> </xsl:stylesheet> Output Output XML <p>Una persona</p><p>Una persona</p> Output HTML (Internet Explorer) Una persona Una persona Valore di un elemento L’elemento xsl:value-of permette di selezionare il contenuto di un elemento di input e inserirlo come output xsl:value-of si può trovare soltanto all’interno di un elemento xsl:template L’attributo select serve a selezionare il valore che deve essere prelevato Esempio Di seguito viene riportato un esempio di elemento xsl:value-of: <xsl:stylesheet version="1.0" xmlns:xsl=“…"> <xsl:template match="persona"> <p>Una persona: <xsl:value-of select="nome"/></p> </xsl:template> </xsl:stylesheet> Output Output XML <p>Una persona: Luca</p><p>Una persona: Mario</p> Output HTML (Internet Explorer) Una persona: Luca Una persona: Mario select Nell’esempio mostrato l’attributo select di xsl:value-of era impostato come di seguito: select="nome“ Dove “nome” è l’attributo del quale si vuole estrarre l’informazione. Più in generale il valore di select deve essere una espressione XPath XPath sarà argomento delle prossime lezioni. Applicazione forzata di modelli L’utilizzo della regola xsl:apply-templates permette di stabilire quali modelli devono essere applicati e in che ordine xsl:apply-templates possiede un attributo select che specifica una regola di tipo xsl:template Esempio <xsl:stylesheet version="1.0" xmlns:xsl=“…"> <xsl:template match="persona"> <p> <xsl:apply-templates select="cognome"/> <xsl:apply-templates select="nome"/> </p> </xsl:template> <xsl:template match="nome"> Nome: <xsl:value-of select="text()"/><br/> </xsl:template> <xsl:template match="cognome"> Cognome: <xsl:value-of select="text()"/><br/> </xsl:template> </xsl:stylesheet> select A differenza del primo esempio in cui l’attributo select di xsl:value-of era impostato come: select="nome“ In questo esempio si ha: select="text()” Dove “text()” è una espressione XPath che sta ad indicare che dell’elemento corrente (nell’esempio si trattava del nome o del cognome) deve essere prelevato il testo in esso contenuto. Output Output XML <p> Cognome: Sabatucci<br/> Nome: Luca<br/> </p> <p> Cognome: Rossi<br/> Nome: Mario<br/> </p> Output Output HTML (Internet Explorer) Cognome: Sabatucci Nome: Luca Cognome: Rossi Nome: Mario Intestazione HTML <xsl:template match="catalogo"> <html> <head> <title>Catalogo persone</title> </head> <body> <xsl:apply-templates select="persona"/> </body> </html> </xsl:template> Output XML <html> <head> <title>Catalogo persone</title> </head> <body> <p> Cognome: Sabatucci<br/> Nome: Luca<br/> </p> <p> Cognome: Rossi<br/> Nome: Mario<br/> </p> </body> </html> Creazione di attributi Modelli XSLT di default <xsl:template match = "/ | *"> <xsl:apply-templates/> </xsl:template> Identifica il nodo radice del doc e tutti i nodi degli elementi. Applica i modelli ai loro nodi child <xsl:template match = “text() | @*"> <xsl:value-of select =“.”/> </xsl:template> Identifica i nodi di testo e i nodi degli attributi (@) e genera l’output dei loro valori <xsl:template match = “processing-instruction() | comment()“/> Identifica i nodi di istruzione di elaborazione e i nodi dei commenti ma non svolge alcuna azione su di essi Sorgente XML <?xml version="1.0"?> <!-- Fig. 12.4 : games.xml --> <!-- Sports Database --> <sports> <game title="cricket"> <id>243</id> <para> More popular among commonwealth nations. </para> </game> <game title="baseball"> <id>431</id> <para> More popular in America. </para> </game> <game title="soccer"> <id>123</id> <para> Most popular sport in the world. </para> </game> </sports> La trasformazione XSL <?xml version = "1.0"?> <xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/ 1999/XSL/Transform"> <xsl:template match = "/"> <xsl:apply-templates/> </xsl:template> <xsl:template match = "sports"> <sports> <xsl:apply-templates/> </sports> </xsl:template> <xsl:template match = "game"> <xsl:element name = "{@title}"> <xsl:attribute name = "id"> <xsl:value-of select = "id"/> </xsl:attribute> <comment> <xsl:value-of select = "para"/> </comment> </xsl:element> </xsl:template> </xsl:stylesheet> Il risultato della trasformazione <?xml version="1.0" encoding="UTF-8"?> <sports> <cricket id="243"> <comment> More popular among commonwealth nations. </comment> </cricket> <baseball id="431"> <comment> More popular in America. </comment> </baseball> <soccer id="123"> <comment> Most popular sport in the world. </comment> </soccer> </sports> Iterazioni e ordinamento Iterazioni e ordinamento E’ possibile elaborare in modo iterativo I nodi selezionati con un’espressione XPath. Sui nodi si può anche operare un ordinamento File dati XML <?xml version="1.0"?> <?xml:stylesheet type = "text/xsl" href = "usage.xsl"?> <book isbn="999-99999-9-X"> <title>Deitel's XML Primer</title> <author> <firstName>Paul</firstName> <lastName>Deitel</lastName> </author> <chapters> <preface num="1" pages="2">Welcome</preface> <chapter num="1" pages="4">Easy XML</chapter> <chapter num="2" pages="2">XML Elements?</chapter> <appendix num="1" pages="9">Entities</appendix> </chapters> <media type="CD"/> </book> La trasformazione XSLT - 1 <?xml version = "1.0"?> <xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"> <xsl:template match = "/"> <html> <xsl:apply-templates/> </html> </xsl:template> <xsl:template match = "book"> <head> <title>ISBN <xsl:value-of select = "@isbn"/> <xsl:value-of select = "title"/></title> </head> Continua La trasformazione XSLT - 2 <body bgcolor = "white"> <h1><xsl:value-of select = "title"/></h1> <h2>by <xsl:value-of select = "author/lastName"/>, <xsl:value-of select = "author/firstName"/></h2> <table border = "1"> <xsl:for-each select = "chapters/preface"> <xsl:sort select = "@num" order = "ascending"/> <tr> <td align = "right"> Preface <xsl:value-of select = "@num"/> </td> <td> <xsl:value-of select = "."/> ( <xsl:value-of select = "@pages"/> pages ) </td> </tr> </xsl:for-each> La trasformazione XSLT - 3 <xsl:for-each select = "chapters/chapter"> <xsl:sort select = "@num" order = "ascending"/> <tr> <td align = "right"> Chapter <xsl:value-of select = "@num"/> </td> <td> <xsl:value-of select = "."/> ( <xsl:value-of select = "@pages"/> pages ) </td> </tr> </xsl:for-each> La trasformazione XSLT - 4 <xsl:for-each select = "chapters/appendix"> <xsl:sort select = "@num" order = "ascending"/> <tr> <td align = "right"> Appendix <xsl:value-of select = "@num"/> </td> <td> <xsl:value-of select = "."/> ( <xsl:value-of select = "@pages"/> pages ) </td> </tr> </xsl:for-each> </table> </body> </xsl:template> </xsl:stylesheet> Il risultato della trasformazione Il risultato della trasformazione <html> <head> <META http-equiv="Content-Type" content="text/html; charset=UTF-16"> <title>ISBN 999-99999-9-X - Deitel's XML Primer</title> </head> <body bgcolor="white"> <h1>Deitel's XML Primer</h1> <h2>by Deitel, Paul</h2> <table border="1"> <tr> <td align="right"> Preface 1</td> <td>Welcome (2 pages )</td> </tr> <tr> <td align="right">Chapter 1</td> <td>Easy XML (4 pages )</td> </tr> Il risultato della trasformazione <tr> <td align="right">Chapter 2</td> <td>XML Elements? (2 pages )</td> </tr> <tr> <td align="right">Appendix 1</td> <td>Entities (9 pages )</td> </tr> </table> </body> </html> Istruzioni Condizionali Il file dati XML <?xml version="1.0"?> <!-- Fig. 5.9 : planner.xml --> <!-- Day Planner XML document --> <planner> <year value="2000"> <date month="7" day="15"> <note time="1430">Doctor's appointment</note> <note time="1620">Physics class at BH291C</note> </date> <date month="7" day="4"> <note>Independence Day</note> </date> <date month="7" day="20"> <note time="0900">General Meeting in room 32-A</note> </date> Il file dati XML <date month="7" day="20"> <note time="1900">Party at Joe's</note> </date> <date month="7" day="20"> <note time="1300">Financial Meeting in room 14-C</note> </date> </year> </planner> La trasformazione XSL <?xml version = "1.0"?> <!-- Fig. 12.11 : conditional.xsl --> <!-- xsl:choose, xsl:when, and xsl:otherwise --> <xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"> <xsl:template match = "/"> <html> <body> Appointments <br/> <xsl:apply-templates select = "planner/year"/> </body> </html> </xsl:template> <xsl:template match = "year"> <strong>Year:</strong> <xsl:value-of select = "@value"/> <br/> <xsl:for-each select = "date/note"> <xsl:sort select = "../@day" order = "ascending" data-type = "number"/> <strong> Day: <xsl:value-of select = "../@day"/>/ <xsl:value-of select = "../@month"/> </strong> <br/> <xsl:choose> <xsl:when test = "@time > '0500' and @time < '1200'"> Morning (<xsl:value-of select = "@time"/>):<xsl:when> <xsl:when test = "@time > '1200' and @time < '1700'"> Afternoon (<xsl:value-of select = "@time"/>):</xsl:when> <xsl:when test = "@time > '1200' and @time < '1700'"> Evening (<xsl:value-of select = "@time"/>):<xsl:when> <xsl:when test = "@time > '1200' and @time < '1700'"> Night (<xsl:value-of select = "@time"/>):<xsl:when> <xsl:otherwise> Entire day: </xsl:otherwise> </xsl:choose> L’elemento choose si usa per scegliere tra varie opzioni (tipo switch del Java) <xsl:value-of select = "."/> <xsl:if test = ". = ''"> n/a </xsl:if> <br/> </xsl:for-each> </xsl:template> </xsl:stylesheet> L’elemento choose si usa per specificare una sola condizione Il risultato Il risultato <html> <body> Appointments<br> <strong>Year:</strong>2000<br> <strong>Day: 4/7</strong><br> Entire day: Independence Day<br> <strong>Day: 15/7</strong><br> Afternoon (1430):Doctor's appointment<br> <strong>Day: 15/7</strong><br> Afternoon (1620):Physics class at BH291C<br> Il risultato <strong>Day: 20/7</strong><br> Morning (0900):General Meeting in room 32-A<br> <strong>Day: 20/7</strong><br> Entire day:Party at Joe's<br> <strong>Day: 20/7</strong><br> Afternoon (1300):Financial Meeting in room 14-C<br> </body> </html> Copiare i nodi Copiare i nodi XSLT permette di copiare i nodi dal file dati XML di origine in quello creato con la trasformazione Ciò si fa con l’elemento copy che copia il nodo di contesto Il file dati XML <?xml version="1.0"?> <?xml:stylesheet type = "text/xsl" href = "copyIntro.xsl"?> <myMessage> <message>Welcome to XSLT!</message> </myMessage> XSLT <?xml version = "1.0"?> <xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"> <xsl:template match = "myMessage"> <xsl:copy> <xsl:apply-templates/> </xsl:copy> </xsl:template> <xsl:template match = "message"> <xsl:copy> How about 'Hi World' for a change! </xsl:copy> </xsl:template> </xsl:stylesheet> Il risultato <?xml version="1.0" encoding="UTF-8"?> <myMessage> <message> How about 'Hi World' for a change! </message> </myMessage> Esercizi Esercizio 1 Scrivere un XSLT che trasformi il documento della figura 12.28 in quello della figura 12.29 seguenti Esercizio 2 Fare il viceversa (trasformare il doc di fig. 12.29 in quello di fig. 12.28) Esercizio 3 Trasformare in HTML i due documenti precedenti Esercizio 4 Trasformare il file planner XML nella struttura mostrata in figura 12.30 Il file dati PLANNER.XML <?xml version="1.0"?> <!-- Fig. 5.9 : planner.xml --> <!-- Day Planner XML document --> <planner> <year value="2000"> <date month="7" day="15"> <note time="1430">Doctor's appointment</note> <note time="1620">Physics class at BH291C</note> </date> <date month="7" day="4"> <note>Independence Day</note> </date> <date month="7" day="20"> <note time="0900">General Meeting in room 32-A</note> </date> Il file dati PLANNER.XML <date month="7" day="20"> <note time="1900">Party at Joe's</note> </date> <date month="7" day="20"> <note time="1300">Financial Meeting in room 14-C</note> </date> </year> </planner> Figura 12.30