470 likes | 575 Views
XSL Transformations. XSL Transformations. Linguaggio utilizzato per manipolare strutture o documenti XML La trasformazione è il processo di creazione di un nuovo documento basato sul documento originale Il processo non modifica il documento originale. XSL Transformations. XML. HTML. XML.
E N D
XSL Transformations
XSL Transformations • Linguaggio utilizzato per manipolare strutture o documenti XML • La trasformazione è il processo di creazione di un nuovo documento basato sul documento originale • Il processo non modifica il documento originale
XSL Transformations XML HTML XML PDF XML DOC XML XML Altri
XSL Transformations Programmazione dichiarativa Con un linguaggio di programmazione dichiarativa, si dice al computer che cosa fare invece di come fare qualcosa
XSL Transformations <?xml version=“1.0” encoding=“UTF-8” ?> <pets> <pet type=“cat”>Max<pet> <pet type=“parrot” color=“red”>Peter<pet> </pets>
XSL Transformations • Esecuzione basata sui dati • Il codice viene eseguito quando il parser incontra un certo dato quando analizza il documento XML
XSL Transformations Ciascun documento XSLT ha il prologo dell’XML <?xml version=“1.0” encoding=“UTF-8” ?> Ciascun documento XSLT è compreso tra i tag <xsl:stylesheet version=“1.0” xmlns:xsl=http://www.w3.org/1999/XSL/Transfrom> … </xsl:stylesheet> In tal modo, i tag dell’XSLT fanno riferimento al namespace xsl
XSL Transformations Il codice XSLT è prevalentemente composto da una serie di regole, dette modelli. Ciascun modello indica un pattern ed un template Ogni volta che il parser incontra un pattern nel documento, esso restituisce in output il template Il pattern viene indicato come valore dell’attributo match <xsl:template match=“dessert”> torta </xsl:template> In questo caso, quando il parser incontra il tag dessert, stampa la parola torta
XSL Transformations • I documenti XML sono organizzati ad albero • Il nodo radice indica il documento stesso • Il nodo radice viene rappresentato dal match / <xsl:template match=“/”> yo </xsl:template> In tal caso, quando il parser comincia a leggere il documento, stampa la parola yo
<?xml version=“1.0” encoding=“UTF-8” ?> <pets> <pet type=“cat”> Max <pet> <pet type=“parrot” color=“red”> Peter <pet> </pets> XSL Transformations • Le regole possono essere concatenate <xsl:template match”/”> <xsl:apply-template /> </xsl:template> Il tag <xsl:apply-template /> indica al parser che deve procedere nella lettura del documento ed applicare le regole attivate
XSL Transformations <xsl:template match”/”> <xsl:apply-template /> </xsl:template> • Se il parser incontra la radice del documento • Continua la lettura del documento <xsl:template match=”pets”> <xsl:apply-template /> </xsl:template> • Il parser incontra il tag pets • Continua a leggere il documento <xsl:template match=”pet”> animale </xsl:template> • Il parser incontra il tag pet • Stampa animale
XSL Transformations • Un modello può essere chiamato direttamente. • Un modello con nome è un modello con un identificatore univoco come nome • Il nome può contenere anche un namespace. Il namespace deve essere definito nell’elemento stylesheet • Un modello viene chiamato attraverso il tag xsl:call-template. Il nome viene specificato con l‘attributo name
XSL Transformations <xsl:template match=“cars”> <xsl:call-template name=“car” /> </xsl:template> <xsl:template name=“car”> Model: <xsl:value-of select=“@model” /> </xsl:template> Nota: il nodo di contesto resta sempre cars, quindi il processore stamperà il valore dell’attributo model di questo elemento. La chiamata di un modello non cambia il nodo corrente
XSL Transformations • Cosa succede se un nodo corrisponde a più modelli? • Posso assegnare a due modelli distinti lo stesso match distinguendoli tramite l’attributo mode <xsl:template match=“person” mode=“generic”> <xsl:value-of select=“./name” /> <xsl:value-of select=“./surname” /> </xsl:template> <xsl:template match=“person” mode=“work”> <xsl:value-of select=“./role” /> </xsl:template> Ho creato due modelli con match uguali ma con mode diversi <xsl:template match=“/”> <xsl:apply-templates mode=“generic” /> <xsl:apply-templates mode=“work” /> </xsl:template> Prima posso applicare i modelli di mode generic, poi quelli di mode work
XSL Transformations • Per stabilire quale modello venga attivato da un nodo, il parser • Seleziona tutti i nodi che hanno l’attributo match • Da questi, seleziona quelli con il modo attivo • Da questi, seleziona quelli per i quali il match corrisponde • Da questi, seleziona quelli con priorità più alta • Se resta più di un modello • lancia l’errore • Altrimenti • Usa il modello • La priorità può essere indicata esplicitamente con l’attributo priority • Se la priorità non è stata indicata, la corrispondenza più precisa ha priorità più alta, e la corrispondenza più generica ha priorità più bassa • Esistono regole precise per stabilire la priorità
XSL Transformations • Per collegarmi a un foglio di stile esterno uso il tag <?xml-stylesheet type=“text/xml” href=“foglio.xsl” ?> • Un documento XSLT può contenere diverse istruzioni per elaborare più fogli di stile che si volgono a media diversi <?xml-stylesheet type=“text/xml” href=“printstyle.xsl”media=“print” ?>
XSL Transformations • Un documento XML può essere descritti come un albero • Si usa l’indirizzamento assoluto se si specifica l’esatta posizione di un elemento rispetto la radice dell’albero • Si usa l’indirizzamento relativo se si specifica la posizione di un elemento relativamente alla posizione corrente
XSL Transformations • Un elemento può avere elementi figlio • Il valore di un elemento comprende anche qualunque elemento o attributo discendente • Un attributo ha un solo elemento figlio associato al valore dell’attributo • Un elemento può contenere solo attributi di nome diverso • Un elemento può contenere più elementi con lo stesso nome • Un nodo è una singola voce che contiene dati dell’albero. Un nodo può essere un elemento o un attributo
XSL Transformations • Nodo corrente: nodo attualmente soggetto ad elaborazione • Insieme di nodi: collezione di nodi accomunati da una qualche proprietà (essere elementi dello stesso tipo, appartenere allo stesso sottoalbero, …)
XSLT: XPath • XPath (XML Path Language) è un linguaggio usato per indirizzare porzioni di un documento XML, o per calcolare valori (stringhe, numeri, booleani) basati sul contenuto di un documento XML. • Il linguaggio XPath è basato su una rappresentazione ad albero del documento XML e fornisce la capacità di navigare lungo l'albero, selezionando i nodi sulla base di una varietà di criteri. • XPath è spesso adoperato come un linguaggio di query semplice e veloce.
XSLT: XPath • Per stabilire quali elementi del documento attivano una regola, si ricorre a XPath • XPath permette di localizzare, in modo efficace parti specifiche di un documento XML • In XPath, un documento XML viene considerato come una struttura ad albero, in cui ogni parte del documento è rappresentato da un nodo
XSLT: XPath • XPath ha sette tipi di nodi: • Radice • Elemento • Attributo • Testo • Commento • Istruzione di elaborazione • Namespace • Eccetto la radice, un nodo dell’albero può essere genitore (parent) di nodi figlio (child)
XPath: operatori • XPath ha 3 operatori principali • | (unisce due gruppi di nodi) • / (separa i passaggi di posizione) • // (abbrevia il path /descendant-or-self::node()/ ) • Gli operatori consentono di manipolare gruppi di nodi per formare altri gruppi
XPath: operatori • Operatori aritmetici: • +, -, *, div, mod • Operatori relazionali • >, <, =, !=, >=, <= • Operatori logici • and, or • Una generica espressione Xpath che viene usata nei modelli XSLT consiste di: • nomeAsse::testNodo[predicato di test]
XPath: operatori <xsl:template match=“firstname|lastname” > <xsl:value-of select=“.” /> </xsl: template> Tale modello si attiva sia con i nodi firstname che con i nodi lastname E se voglio intercettare sia gli elementi che gli attributi con un certo nome? In tal caso si ricorre all’attributo select del tag xsl:apply-template <xsl:template match=“” > <xsl:apply-template select=“name|@name” /> </xsl:template> L’espressione name|@name indica l’unione dei tag name e degli attributi name
Produce: Very cheap books Il Mastino dei Baskerville XPath: operatori <xsl:template match=“bookstore” > <h2>Very cheap books<h2> <xsl:for-each select=“./book[@price<35]” /> <p><xsl:value-of select=”title” /></p> </xsl:for-each> </xsl: template> Applicato a: <bookstore> <book price=”47.00”> <title>Il Maestro e Margherita</tite> </book> <book price=”12.50”> <title>Il Mastino dei Baskerville</title> </book> </bookstore>
XSLT: le funzioni • Le funzioni permettono di svolgere determinate operazioni sul gruppo di nodi restituito da un path di posizione
XSL Transformations • Inserire in output del testo • È sufficiente inserire il testo nel modello <xsl:template match=“/”> ciao </xsl:template> Il parser stampa in uscita la stringa ciao
XSL Transformations • Inserire in output di elementi • È sufficiente inserire l’elemento nel modello <xsl:template match=“/”> <el>ciao</el> </xsl:template> Il parser stampa in uscita <el>ciao</el>
XSL Transformations • Inserire in output di elementi con nome generato <xsl:template match=“/”> <xsl:element name=“el”>ciao</xsl:element> </xsl:template> Il parser stampa in uscita <el>ciao</el>
XSL Transformations • Inserire in output di attributi <xsl:template match=“persons”> <table> <xsl:attribute name=“border”>1</xsl:attribute> <xsl:apply-templates /> </table> </xsl:template> Il parser stampa in uscita <table border=“1”> … </table>
XSL Transformations • Inserire in output un gruppo di attributi • Definisco un insieme di attributi <xsl:attribute-set name=“tableattr”> <xsl:attribute name=“border”>1</xsl:attribute> <xsl:attribute name=“width”>2</xsl:attribute> </xsl:attribute-set> • Uso l’insieme definito <xsl:template match=“persons”> <xsl:element name=“table” use-attribute-sets=“tableattr” /> <xsl:apply-templates /> </xsl:template> Il parser stampa in uscita <table border=“1” width=“2”> … </table>
XSL Transformations • Uso più insiemi di attributi • Definisco un insieme di attributi <xsl:attribute-set name=“borderattr”> <xsl:attribute name=“border”>1</xsl:attribute> </xsl:attribute-set> <xsl:attribute-set name=“widthattr”> <xsl:attribute name=“width”>2</xsl:attribute> </xsl:attribute-set> • Uso l’insieme definito <xsl:template match=“persons”> <xsl:element name=“table” use-attribute-sets=“borderattr widthattr” /> <xsl:apply-templates /> </xsl:template> Il parser stampa in uscita <table border=“1” width=“2”> … </table>
XSL Transformations • Inserire in output il nodo contesto • 2 varianti <xsl:template match=“persons”> <xsl:copy> <xsl:apply-templates /> </xsl:copy> </xsl:template> In questo caso si fa una copia dei nodi risultati dalla chiamata di apply-templates <xsl:template match=“persons”> <xsl:copy /> </xsl:template> In questo caso si fa una copia del nodo persons
XSL Transformations • copy fa una copia del solo nodo di contesto, ignorando i nodi eventualmente contenuti • Per fare una deep copy, usare copy-of • 2 varianti <xsl:template match=“persons”> <xsl:copy-of select=“.” /> </xsl:template> In questo caso si fa una copia del nodo persons e di tutti i nodi contenuti
XSL Transformations • Inserire in output un commento <xsl:template match=“persons”> <xsl:comment> questo sarà inserito come commento </xsl:comment> <xsl:apply-templates /> </xsl:template>
XSL Transformations • Inserire in output un’istruzione di elaborazione <xsl:template match=“persons”> <xsl:processing-instruction name=“nome”> href=“prova” </ xsl:processing-instruction > <xsl:apply-templates /> </xsl:template> • Il sistema stampa <?nome href=“prova” ?>
XSL Transformations Elaborazione condizionale e iterativa • È possibile definire dei cicli for per elaborare una serie di nodi <employees> <employee name=“aaa”> <phonenumber type=“home”>111</ phonenumber> <phonenumber type=“fax”>222</ phonenumber> <phonenumber type=“mobile”>333</ phonenumber> <employee> <employee name=“aaa”> <phonenumber type=“home”>111</ phonenumber> <employee> </employees> Voglio ciclare tutti gli impiegati e, per ciascun impiegato, tutti i numeri
XSL Transformations <xsl:template match=“/”> Comincio dall’inizio del documento <xsl:for-each select=“employees/employee”> ciclo tutti i nodi employee con parent employees <xsl:value-of select=“@name” /> stampo il valore dell’attributo name <xsl:for-each select=“phonenumber”> ciclo tutti i nodi phone number <xsl:value-of select=“@type” /> stampo il valore dell’attributo type <xsl:value-of select=“.” /> stampo il valore del nodo attuale (phonenumber) </xsl:for-each> </xsl:for-each> </xsl:template>
XSL Transformations • È possibile filtrare i nodi in base al loro nome o valore … <xsl:for-each select=“phonenumber[@type=“home”]”> Filtra solo i nodi il cui attributo type ha valore home … </xsl:for-each>
XSL Transformations • I nodi figli hanno una naturale numerazione che segue l’ordine di scrittura nel file e che parte da 1 … <xsl:for-each select=“employees/employee/phonenumber[2]”> Cicla tutti i secondi nodi phonenumber figli di un nodo employee, a loro volta figli da un nodo employees … </xsl:for-each> <xsl:for-each select=“employees/employee/phonenumber[position()=2]”> Identico all’esempio precedente … </xsl:for-each> <xsl:for-each select=“employees/employee/phonenumber[last()]”> La funzione last() restituisce l’indice dell’ultimo nodo child di tipo phonenumer, per ciascun employee … </xsl:for-each>
XSL Transformations • È possibile indicare delle condizioni affinché i nodi siano selezionati <xsl:for-each select=“employees/employee”> Ciclo i nodi <xsl:value-of select=“@name” /> stampo il valore dell’attributo name <xsl:if test=“position()!=last()”> </xsl:if> se non sono all’ultimo nodo, metto spazio <xsl:if test=“position()=last()”>.</xsl:if> se sono all’ultimo nodo, metto punto </xsl:for-each>
XSL Transformations • Posso definire più condizioni <xsl:for-each select=“phonenumber”> <xsl:choice> <xsl:when type=“@type=‘mobile’”> mobile: <xsl:value-of select=“.” /> </xsl:when> <xsl:when type=“@type=‘fax’”> fax: <xsl:value-of select=“.” /> </xsl:when> <xsl: otherwise> phone: <xsl:value-of select=“.” /> </otherwise> </xsl:choice> </xsl:for-each>
XSL Transformations • Posso combinare più espressioni phonenumber[position()=1 e @type=‘home’] phonenumber[position()=1 or @type=‘home’] phonenumber[ not(@type=‘home’) ] • Esistono anche le funzioni booleane true() e false()
XSL Transformations • Per eliminare il prologo XML dall’output <xsl:output method=“xml” version=“1.0”omit-xml-declaration=“yes” /> • Altri possibili valori che posso assegnare a method sono: • html: se il file prodotto è di formato html • text: se il file prodotto è di formato txt • format:pdf: se il file prodotto è di formato pdf • …
XSL Transformations • Alcuni caratteri sono gestiti in maniera speciale in XML Per es: il carattere < viene rappresentato con > • In alternativa, si può ricorrere a nodi CDATA <nodo> <![CDATA[ 2 < 3 ]]> </nodo> • In memoria la stringa “2 < 3” viene comunque memorizzata come “2 > 3”
L’output è sempre <op>2 > 3</op> <op>2 > 3</op> Per avere l’espressione all’interno di un nodo CDATA uso il tag <xsl:output cdata-section-elements=”op” /> In questo caso l’output è; <op><![CDATA[2 < 3]]></op> <op><![CDATA[2 < 3]]></op> XSL Transformations <xsl:template match=“/”> <xsl:copy-of select=“.”/> </xsl:template> <ops> <op><![CDATA[2 < 3]]></op> <op>2 > 3</op> </ops>