[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico] [volume] [parte]


Capitolo 451.   Introduzione ai fogli di stile XSLT

XSLT è un linguaggio realizzato in forma di file XML, con il quale si definisce una trasformazione di un file XML in un altro file. Generalmente, il file di destinazione è un altro file XML, anche se può comunque essere qualcosa di diverso. La sigla sta precisamente per XSL transformations (ovvero Extensible stylesheet language transformations), a indicare che il linguaggio è scritto in quello che viene chiamato «foglio di stile XSL» e serve a trasformare i dati originali in qualcosa di conveniente ai propri scopi. In altri termini, si tratta di un linguaggio che consente di estrarre le informazioni contenute in un file XML, per generare con queste ciò che serve.

Figura 451.1. Utilizzo del linguaggio XSLT per la trasformazione di un file XML.

utilizzo del linguaggio XSLT per la trasformazine di un file XML

Naturalmente, l'elaborazione di un file XML secondo il linguaggio XSLT richiede un programma apposito. In questo capitolo viene mostrato a l'uso di Xalan (sezione 451.6).

La trattazione che qui viene fatta a proposito dei fogli di stile XSLT è limitata alle funzionalità principali. Per un approfondimento si può consultare la documentazione elencata nella bibliografia alla fine del capitolo.

451.1   Struttura ad albero, percorsi e modelli di confronto

Un documento XML, ai fini della sua elaborazione, viene visto come una struttura ad albero, dove ogni componente rappresenta un nodo di questo. Si osservi l'esempio seguente, che rappresenta un file XML molto semplice:

<?xml version="1.0" encoding="UTF-8" ?>
<relazione lang="it">
<titolo>Relazione introduttiva su XML</titolo>
<data>11/11/2011</data>
<contenuto>
<paragrafo>XML sta per Extensible Markup Language.</paragrafo>
<paragrafo>Bla, bla, bla...</paragrafo>
<firma>Pinco Pallino</firma>
</contenuto>
</relazione>

Si potrebbe rappresentare schematicamente l'albero di questo documento come si vede nella figura successiva:

dichiarazione di un elemento SGML

Nello schema mostrato si deve osservare che elementi, attributi e testo contenuto negli elementi, costituiscono nodi separati.

Per identificare un nodo dell'albero, si usa una notazione che assomiglia ai percorsi dei file system Unix. A titolo di esempio vengono mostrati tutti gli elementi e gli attributi XML degli schemi già apparsi, secondo la sequenza originale, con percorsi assoluti:

/
/relazione
/relazione/@lang
/relazione/titolo
/relazione/data
/relazione/contenuto
/relazione/contenuto/paragrafo
/relazione/contenuto/paragrafo
/relazione/contenuto/firma

Naturalmente esistono anche percorsi relativi, quando manca la barra obliqua iniziale che rappresenta la radice: questi fanno riferimento al nodo corrente nell'ambito del contesto a cui ci si riferisce.

La sintassi con cui si possono definire questi percorsi è stabilita dal linguaggio XPath, ovvero XML path language. Si tratta di un sistema abbastanza complesso che non viene mostrato qui nel dettaglio. Per quanto riguarda il linguaggio XSLT i percorsi vengono usati per definire un modello di confronto con i nodi di un documento XML; nell'ambito di questi modelli di confronto si utilizzano delle notazioni particolari rispetto alla convenzione generale costituita da XPath. La tabella 451.5 riporta alcuni esempi di questi modelli.

Tabella 451.5. Alcuni modelli di confronto per individuare i nodi di un documento XML.

Modello Descrizione
/
Una barra obliqua da sola individua il nodo radice.
text()
Individua qualunque nodo di testo.
node()
Individua qualunque nodo, esclusi gli attributi e la radice.
.
self::node()
Una di queste due notazioni, indifferentemente, individua il nodo corrente.
..
parent::node()
Una di queste due notazioni, indifferentemente, individua il nodo genitore di quello corrente.
elemento
child::elemento
Un nome scritto senza l'inserzione di simboli speciali rappresenta un elemento. La seconda notazione è completa.
elemento[n]
Individua l'n-esimo elemento con quel nome, che si trova all'interno dell'elemento che lo contiene. Osservando gli esempi mostrati in precedenza, paragrafo[1] può rappresentare il primo elemento paragrafo che si trova all'interno dell'elemento contenuto.
@attributo
attribute::attributo
Un nome preceduto da una chiocciolina rappresenta un attributo. La seconda notazione è completa.
*
L'asterisco corrisponde a qualunque elemento.
@*
L'asterisco preceduto da una chiocciolina corrisponde a qualunque attributo.
elemento_1|elemento_2
I nomi di due elementi, separati da una barra verticale, indicano la corrispondenza con l'uno o con l'altro.
@attributo_1|@attributo_2
I nomi di due attributi, separati da una barra verticale, indicano la corrispondenza con l'uno o con l'altro.
elemento_1/elemento_2
La barra obliqua separa i nodi di un percorso; in questo caso, si vuole individuare l'elemento elemento_2 che è contenuto da elemento_1.
elemento/@attributo
In questo caso si vuole fare riferimento a un attributo di un certo elemento.
elemento_1//elemento_2
elemento_1\
  \/descendant-or-self::node()/\
  \elemento_2
Due barre oblique indicano una discendenza non meglio precisata: qui, elemento_2 è contenuto all'interno di elemento_1, direttamente oppure all'interno di annidamenti ulteriori.

451.2   Struttura generale del foglio di stile XSLT

Un foglio di stile XSLT è un documento XML con una struttura particolare, abbinato al dominio applicativo <http://www.w3.org/1999/XSL/Transform> (sezione 450.5). Normalmente, il prefisso associato a questo dominio applicativo è xsl, pertanto, l'elemento principale è xsl:stylesheet, oppure xsl:transform, indifferentemente:

<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    [altri_attributi]>
    [contenuto]
</xsl:stylesheet>
<xsl:transform
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    [altri_attributi]>
    [contenuto]
</xsl:transform>

Anche senza definire esplicitamente alcun tipo di trasformazione, si ottiene ugualmente un risultato elaborando un file XML, attraverso delle regole di trasformazione predefinite, con le quali, in buona sostanza, si ottiene il testo del file XML, senza i marcatori che delimitano gli elementi. Per esempio, si può prendere il file XML già presentato all'inizio del capitolo, associandogli il foglio di stile seguente:

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

Supponendo che il file XML si chiami prova.xml e che il foglio di stile sia prova.xsl, si potrebbe usare Xalan nel modo seguente:

xalan -IN prova.xml -XSL prova.xsl -OUT prova.txt[Invio]

Ecco cosa si ottiene nel file prova.txt:

<?xml version="1.0" encoding="UTF-8"?>

Relazione introduttiva su XML
11/11/2011

XML sta per Extensible Markup Language.
Bla, bla, bla...
Pinco Pallino

451.3   Modelli di confronto e trasformazione

La definizione di un criterio di trasformazione dei nodi del documento XML di origine in quello che si vuole ottenere, avviene principalmente per mezzo di modelli di confronto, attraverso un elemento del foglio di stile denominato xsl:template. La traduzione del termine template, ovvero «mascherina», rende bene l'idea del concetto: gli elementi xsl:template del foglio di stile definiscono un modello di confronto con cui selezionano alcuni nodi del documento XML di origine; su questi nodi applicano delle trasformazioni.

<xsl:template
    match="modello_di_confronto"
    [altri_attributi]>
    trasformazione
</xsl:template>

Il modello di confronto viene definito secondo le regole che in parte sono state descritte nella tabella 451.5; per esempio, il blocco seguente individua il nodo radice:

<xsl:template match="/">
    ...
    ...
</xsl:template>

Per comprendere meglio cosa accade, si prenda il solito esempio di file XML già considerato in precedenza e si applichi il foglio di stile seguente:

<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/relazione/contenuto">
        ciao ciao
    </xsl:template>
</xsl:stylesheet>

Come si vede, è stato inserito un solo elemento xml:template che seleziona l'elemento contenuto, che si trova all'interno di relazione (che a sua volta è l'elemento principale del documento XML). Quando si individua questo elemento, viene inserito il testo «ciao ciao». Valgono le stesse convenzioni dei nomi dei file già viste in precedenza:

xalan -IN prova.xml -XSL prova.xsl -OUT prova.txt[Invio]

Ecco cosa si ottiene nel file prova.txt:

<?xml version="1.0" encoding="UTF-8"?>

Relazione introduttiva su XML
11/11/2011

        ciao ciao

In pratica, le regole di trasformazione predefinite hanno inserito il contenuto degli elementi titolo e data. Quindi, l'elemento contenuto, con tutto quello che esiste al suo interno, è stato sostituito con la stringa «ciao ciao».

Per fare in modo che vengano presi in considerazione anche gli elementi contenuti all'interno di ciò che viene individuato, si utilizza l'elemento xsl:apply-templates, che di solito è vuoto:

<xsl:template
    match="modello_di_confronto"
    [altri_attributi]>
    ...
    <xsl:apply-templates
        [select="modello_di_selezione"]
        [altri_attributi]>
        ...
    </xsl:apply-templates>
    ...
</xsl:template>

Per esempio, se il foglio di stile di prova viene modificato nel modo seguente:

<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/relazione/contenuto">
        prima
        <xsl:apply-templates />
        dopo
    </xsl:template>
</xsl:stylesheet>

La trasformazione genera questo file:

<?xml version="1.0" encoding="UTF-8"?>

Relazione introduttiva su XML
11/11/2011

        prima
        
XML sta per Extensible Markup Language.
Bla, bla, bla...
Pinco Pallino

        dopo

In pratica, si consente alle regole di trasformazione predefinite (dal momento che non ce ne sono altre nell'esempio) di occuparsi degli elementi contenuti all'interno dell'elemento contenuto, cosa che produce semplicemente l'estrazione del testo che questi circoscrivono. Tutto questo avviene perché «l'istruzione» apply-templates serve proprio a richiamare gli altri modelli di confronto (e trasformazione) per quanto è contenuto in ciò che è stato individuato.

Dal momento che nell'esempio non ci sono altri modelli di confronto e trasformazione, è evidente che si tratta soltanto di quelli predefiniti.

L'elemento xsl:apply-templates può avere un attributo molto importante, select, che consente di specificare su cosa continuare il confronto con altri modelli; in pratica consente di limitare, o controllare, la ricorsione. Si osservi la variante seguente del foglio di stile:

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:template match="/relazione/contenuto">
        prima
        <xsl:apply-templates select="paragrafo" />
        dopo
    </xsl:template>
</xsl:stylesheet>

Per prima cosa è bene osservare che il modello indicato con l'attributo select rappresenta un percorso relativo, che secondo il contesto è riferito esattamente a /relazione/contenuto/paragrafo. In base a questa selezione, si vuole che nell'ambito del contenuto dell'elemento (o degli elementi) /relazione/contenuto, la ricorsione successiva prenda in considerazione soltanto gli elementi paragrafo. Ecco cosa si ottiene; come si vede, il testo dell'elemento firma è stato ignorato:

<?xml version="1.0" encoding="UTF-8"?>

Relazione introduttiva su XML
11/11/2011

        prima
        XML sta per Extensible Markup Language.Bla, bla, bla...
        dopo

Naturalmente, è possibile utilizzare xsl:apply-templates più volte all'interno dello stesso modello di confronto e trasformazione, anche così:

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:template match="/relazione/contenuto">
        Io sottoscritto, <xsl:apply-templates select="firma" />,
        affermo che:
        <xsl:apply-templates select="paragrafo" />

        Firmato:
        <xsl:apply-templates select="firma" />
    </xsl:template>
</xsl:stylesheet>

Ecco il risultato che si può ottenere:

<?xml version="1.0" encoding="UTF-8"?>

Relazione introduttiva su XML
11/11/2011

        Io sottoscritto, Pinco Pallino,
        affermo che:
        XML sta per Extensible Markup Language.Bla, bla, bla...

        Firmato:
        Pinco Pallino

I modelli di confronto e trasformazione possono basarsi su riferimenti relativi ai nodi, se non ha importanza la collocazione esatta di questi nell'albero del documento XML di origine. Si osservi l'esempio seguente:

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:template match="paragrafo">
        "<xsl:apply-templates />"
    </xsl:template>
</xsl:stylesheet>

In questo caso, si evidenziano gli elementi paragrafo, attorno ai quali si vuole appaiano gli apici doppi; tutto il resto viene gestito in modo predefinito:

<?xml version="1.0" encoding="UTF-8"?>

Relazione introduttiva su XML
11/11/2011


        "XML sta per Extensible Markup Language."
    

        "Bla, bla, bla..."
    
Pinco Pallino

Come accennato, l'elemento xsl:apply-templates del foglio di stile XSLT, normalmente è vuoto. Quando contiene qualcosa, ciò serve per elaborare il risultato della scansione che lo riguarda. In pratica, xsl:apply-templates serve a richiamare i modelli di confronto e trasformazione successivi, in modo da inserire il risultato di queste elaborazioni nel punto in cui si trova, ma se questo elemento non è vuoto, le «istruzioni» che contiene servono a interferire con le elaborazioni successive, per esempio per riordinare i dati ottenuti. Questo tipo di utilizzo di xsl:apply-templates non viene descritto.

451.4   Testo

Negli esempi delle sezioni precedenti, in varie occasioni è stato inserito del testo aggiuntivo nella trasformazione del documento XML di origine. In questo modo è possibile anche aggiungere marcatori e altre componenti, in base agli scopi che ci si prefigge con la trasformazione.

Quando un elemento contiene solo spazi bianchi (spazi veri e propri, tabulazioni orizzontali e interruzioni di riga), il nodo relativo può essere eliminato dalla struttura. In generale, salvo che sia specificato diversamente, nel documento XML di origine vengono preservati tutti gli spazi, mentre nel foglio di stile sono preservati solo quelli contenuti negli elementi xsl:text.

451.4.1   Formato generale del risultato della trasformazione

Esistono diverse modalità di funzionamento a cui si adegua la trasformazione del documento XML, in base al tipo di file che si vuole ottenere. Questa modalità di funzionamento si seleziona con l'elemento xsl:output:

<xsl:output
    method="metodo"
    version="versione"
    encoding="codifica"
    omit-xml-declaration="yes"|"no"
    doctype-public="dichiarazione_dtd_public"
    doctype-system="dichiarazione_dtd_system"
    [altri_attributi] />

Come si vede dal modello sintattico, si tratta di un elemento del foglio di stile che non ha lo scopo di contenere qualcosa e tutto è indicato attraverso attributi.

L'attributo più importante è method, al quale si associano normalmente le parole chiave xml, html e text, per indicare rispettivamente che si vuole ottenere un risultato in formato XML, HTML o un file di testo senza una conformazione particolare conosciuta. In generale, se non si specifica il formato del file che si va a generare, si intende XML, cosa che dovrebbe spiegare il motivo per cui negli esempi mostrati in precedenza appare la dichiarazione XML anche se il file ottenuto è semplicemente un testo puro e semplice.

Come si può intuire, a seconda del tipo di «metodo» prescelto, gli altri attributi possono acquisire o perdere significato.

Tabella 451.19. Alcuni attributi di xsl:output utili quando il risultato dell'elaborazione deve essere un file XML.

Attributo Descrizione
method="xml"
Dichiara il metodo di trasformazione in un documento XML. Alcuni caratteri (come & e <) vengono trasformati nelle rispettive entità generali standard.
version="versione"
Dichiara il numero di versione del formato XML. Il valore predefinito è 1.0.
encoding="codifica"
Dichiara il tipo di codifica del file da generare. Sono valide sempre le sigle UTF-8 e UTF-16, ma possono essere disponibili altre sigle, come per esempio ISO-8859-n.
omit-xml-declaration=\
  \"yes"|"no"
Consente di omettere (se si assegna il valore yes) la dichiarazione XML iniziale.
indent="yes"|"no"
Permette di richiedere un incolonnamento degli elementi nel risultato della trasformazione.
doctype-public="dtd_public"
Permette di specificare la dichiarazione del DTD, utilizzando un identificatore pubblico, come potrebbe essere: -//W3C//DTD XHTML 1.1//EN.
doctype-system="dtd_system"
Permette di specificare la dichiarazione del DTD, indicando come riferimento un file.

Tabella 451.20. Alcuni attributi di xsl:output utili quando il risultato dell'elaborazione deve essere un file HTML.

Attributo Descrizione
method="html"
Dichiara il metodo di trasformazione in un documento HTML. Alcuni caratteri vengono trasformati usando le entità generali standard.
version="versione"
Dichiara il numero di versione del formato HTML. Il conoscere la versione permette di verificare la validità del foglio di stile anche in base alla validità del codice HTML che si va a generare. Il valore predefinito è 4.0.
encoding="codifica"
Dichiara il tipo di codifica del file da generare. Sono valide sempre le sigle UTF-8 e UTF-16, ma possono essere disponibili altre sigle, come per esempio ISO-8859-n.
doctype-public="dtd_public"
Permette di specificare la dichiarazione del DTD, utilizzando un identificatore pubblico, come potrebbe essere: ISO/IEC 15445:2000//DTD HTML//EN.
doctype-system="dtd_system"
Permette di specificare la dichiarazione del DTD, indicando come riferimento un file.

Tabella 451.21. Alcuni attributi di xsl:output utili quando il risultato dell'elaborazione deve essere un file di testo non meglio identificabile.

Attributo Descrizione
method="text"
Dichiara il metodo di trasformazione in un file di testo. In questo caso non avviene alcuna trasformazione dei caratteri, come invece può avvenire con le trasformazioni in XML o in HTML.
encoding="codifica"
Dichiara il tipo di codifica del file da generare. Sono valide sempre le sigle UTF-8 e UTF-16, ma possono essere disponibili altre sigle, come per esempio ISO-8859-n.

451.4.2   Inserimento di testo aggiuntivo

Generalmente è sufficiente aggiungere del testo estraneo all'interno del foglio di stile XSLT, nell'ambito degli elementi xsl:template, per fare in modo che questo venga inserito nel risultato finale. Per avere un controllo maggiore si può usare l'elemento xsl:text, che tra le altre cose permette di inserire blocchi di spazi quando diversamente verrebbero eliminati:

<xsl:text
    [disable-output-escaping="yes"|"no"]>
    testo
</xsl:text>

L'attributo disable-output-escaping permette, se si assegna il valore yes, di disabilitare la sostituzione di alcuni caratteri in entità generali standard (questo vale solo per le trasformazioni che prevedono nella destinazione un formato XML o HTML, perché nel caso di trasformazioni in formato testo, questa sostituzione non viene mai eseguita). Come si può intendere, la funzionalità è disabilitata in modo predefinito, pertanto, normalmente si ottiene la sostituzione di questi caratteri.

In alcune circostanze è necessario inserire del testo nel foglio di stile XSLT che non deve essere interpretato prima della trasformazione, lasciandolo in modo letterale. Per questo si usa normalmente una sezione marcata di tipo CDATA, come nell'esempio seguente, dove si vede l'intenzione di inserire uno stile CSS nel documento finale che è un file HTML:

    <xsl:template match="/">
        <HTML>
        <HEAD>
            <TITLE>senza titolo</TITLE>
        <xsl:text disable-output-escaping="yes">
<![CDATA[<STYLE TYPE="text/css">
<!--
BODY {
    background-color: rgb(255, 255, 255)
}
H1 {
    text-align:       right;
    color:            rgb(230, 100, 180)
}
-->
</STYLE>]]>
        </HEAD>
        <BODY>
        <xsl:apply-templates />
        </BODY>
    </xsl:template>

451.4.3   Estrazione del valore contenuto in un nodo

Il testo contenuto in un nodo viene inserito nel documento finale attraverso l'elemento xsl:value-of del foglio di stile. Esiste anche un modello di confronto e trasformazione predefinito che esegue questa operazione per tutti i nodi di testo, pertanto, negli esempi di fogli di stile non si è ancora presentata la necessità di mostrarne l'uso:

<xsl:value-of
    select="modello_di_selezione"
    [disable-output-escaping="yes"|"no"] />

Come si vede dal modello sintattico, l'elemento xsl:value-of si usa vuoto e, per ottenere il «valore» di qualcosa, occorre specificarlo attraverso un modello di selezione, come avviene con l'elemento xsl:apply-templates.

Anche questo elemento prevede l'attributo disable-output-escaping come descritto a proposito di xsl:text.

L'elemento xsl:value-of si può usare per estrarre il testo contenuto in un elemento del documento di origine, oppure per fare altrettanto da un attributo; in generale, è più frequente l'uso di xsl:value-of per estrarre il testo di un attributo, come nell'esempio seguente:

<xsl:template match="relazione">
    Questo documento utilizza il linguaggio <xsl:value-of select="@lang" />.
</xsl:template>

In questo caso, quando si raggiunge un elemento denominato relazione, nel documento XML di origine, viene estratto il valore dell'attributo lang di questo e inserito in una frase, ignorando qualunque altra cosa che possa riguardare l'elemento in questione.

Quando il documento di destinazione è di tipo XML o HTML, è probabile che si vadano a descrivere dei marcatori che contengono la dichiarazione di attributi. Quando negli attributi si vuole inserire un valore estratto da un nodo del documento XML di origine, non si può usare l'elemento xsl:value-of; al suo posto si usano delle parentesi graffe, come nell'esempio seguente:

<xsl:template match="relazione">
    <HTML LANG="{@lang}">
    <BODY>
    <xsl:apply-templates />
    </BODY>
    </HTML>
</xsl:template>

Questa volta, come si può vedere, si va a costruire un documento HTML, dove serve il valore dell'attributo lang dell'elemento relazione del file di partenza.

451.5   Creazione di componenti XML e HTML

Quando il formato di destinazione della trasformazione è un file XML o HTML, è possibile creare alcune componenti tipiche di questi file con l'ausilio di elementi appositi nel foglio di stile XSLT.

451.5.1   Creazione di elementi e di attributi

Quando per qualche ragione è difficile inserire letteralmente il testo che rappresenta i marcatori di un elemento nel documento finale, si può usare nel foglio di stile XSLT l'elemento xsl:element:

<xsl:element
    name="nome_elemento"
    [altri_attributi]>
    contenuto
</xsl:element>

Per dichiarare un attributo si può usare l'elemento xsl:attribute:

<xsl:attribute
    name="nome_attributo"
    [altri_attributi]>
    contenuto
</xsl:element>

L'esempio seguente mostra l'uso di questi due elementi, per la costruzione della prima parte di un documento HTML, dove in particolare si vede anche l'uso di xsl:value-of:

<xsl:template match="/">
    <xsl:element name="HTML">
        <xsl:attribute name="LANG">
            <xsl:value-of select="relazione/@lang" />
        </xsl:attribute>
        <HEAD>
        <TITLE><xsl:value-of select="relazione/titolo" /></TITLE>
        </HEAD>
        <BODY>
        <xsl:apply-templates />
        </BODY>
    </xsl:element>
</xsl:template>

Osservando l'esempio si intende che il documento XML di origine contiene l'elemento relazione all'inizio della gerarchia; inoltre al suo interno si trova l'elemento titolo che viene usato per completare l'intestazione del file HTML.

451.5.2   Creazione di commenti e di istruzioni di elaborazione

Quando il formato di destinazione è di tipo XML o HTML è possibile inserire dei commenti attraverso l'elemento xsl:comment nel foglio di stile XSLT:

<xsl:comment>
    contenuto
</xsl:comment>

In modo analogo, è possibile inserire istruzioni di elaborazione quando il formato di destinazione è di tipo XML, con l'elemento xsl:processing-instruction:

<xsl:processing-instruction
    name="nome_istruzione">
    contenuto
</xsl:processing-instruction>

Si osservi l'esempio seguente:

<xsl:template match="/">
    <xsl:processing-instruction name="xml-stylesheet">href="esempio.css"
    type="text/css"</xsl:processing-instruction>
    <xsl:comment>Ecco un commento</xsl:comment>
    <xsl:apply-templates />
</xsl:template>

In questo modo, all'inizio del documento di destinazione si ottiene il testo seguente:

<?xml-stylesheet href="esempio.css"
    type="text/css"?>
<!--Ecco un commento-->

451.6   Xalan

Xalan (1) è un elaboratore XSLT disponibile sia in Java, sia in C++. Qui si fa riferimento all'uso di Xalan-C++, ovvero a un programma compilato in modo da avere un eseguibile che non richiede altre forme di interpretazione:

xalan -IN documento_xml_originale -XSL foglio_di_stile \
  \-OUT file_da_generare [altre_opzioni]

Il modello sintattico mostrato è più che sufficiente per usare bene Xalan; per le altre opzioni disponibili si può consultare la pagina di manuale xalan(1).

Durante l'elaborazione, Xalan emette alcune informazioni ed eventualmente delle segnalazioni di errore, che dovrebbero tornare utili per correggere il foglio di stile XSLT. Si osservi che quando si procede a una trasformazione che deve generare un documento XML o HTML, Xalan si sofferma anche su errori relativi al formato finale. Per esempio, l'estratto seguente, riferito proprio alla generazione di codice HTML genera un errore a causa della mancata chiusura dell'elemento HEAD nel file che si ottiene:

      5 <xsl:template match="/">
      6     <HTML>
      7     <HEAD>
      8     <TITLE><xsl:value-of select="relazione/titolo" /></TITLE>
      9     <BODY>
     10     <xsl:apply-templates />
     11     </BODY>
     12 </xsl:element>

Supponendo che il file XML originale sia prova.xml, che il foglio di stile XSLT sia contenuto nel file prova.xsl e che si voglia generare il file prova.html, si dovrebbe procedere con il comando seguente:

xalan -IN prova.xml -XSL prova.xsl -OUT prova.html[Invio]

In questo caso, si ottiene l'errore già descritto:

========= Parsing prova.xsl ==========

Fatal Error at (file prova.xsl, line 12, column 18): \
  \Expected end of tag 'HEAD' SAXParseException Message is: Expected end of tag 'HEAD' \
  \(prova.xsl, line 12, column 18)

I riferimenti ai numeri di riga dell'esempio sono corretti, pertanto si può osservare che gli errori vengono segnalati in posizioni abbastanza lontane rispetto alla loro collocazione effettiva.

451.7   Esempio completo

Nelle sezioni seguenti vengono mostrati diversi fogli di stile XSLT per ottenere altrettante trasformazioni a partire da un file XML già mostrato in precedenza. Qui viene riportato nuovamente, con qualche piccola modifica e con l'aggiunta della dichiarazione del DTD incorporata:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE relazione [
    <!ELEMENT relazione     (titolo?, data, contenuto)>
    <!ATTLIST relazione
        xml:lang   CDATA    "">
    <!ELEMENT titolo        (#PCDATA)>
    <!ELEMENT data          (#PCDATA)>
    <!ELEMENT contenuto     (paragrafo+, firma+)>
    <!ELEMENT paragrafo     (#PCDATA)>
    <!ELEMENT firma         (#PCDATA)>
]>

<relazione lang="it">
<titolo>Relazione introduttiva su XML</titolo>

<data>11/11/2011</data>

<contenuto>

<paragrafo>XML sta per Extensible Markup Language.    bla bla bla...
Perché,... così,... perciò,... sarà...</paragrafo>

<paragrafo>Bla, bla, bla....</paragrafo>

<firma>Pinco Pallino</firma>

</contenuto>
</relazione>

Si osservi che questo file, come si vede dalla dichiarazione iniziale, deve usare la codifica UTF-8; di conseguenza, le lettere accentate utilizzano più di un byte per essere rappresentate.

451.7.1   Trasformazione in un sorgente LaTeX

Per la trasformazione in un sorgente LaTeX si deve utilizzare un foglio di stile XSLT che elabora il risultato in modalità testo:

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:output method="text" encoding="UTF-8" />
    <xsl:template match="/">
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[italian,english]{babel}
\begin{document}
            <xsl:apply-templates />
\end{document}
        </xsl:template>
        <xsl:template match="titolo">
\section{<xsl:apply-templates />}
    </xsl:template>
</xsl:stylesheet>

Si può osservare che non sono state stabilite delle regole di trasformazione per gli elementi data, paragrafo e firma, perché allo scopo risultano sufficienti le regole predefinite. Inoltre, le parentesi graffe sono usate fuori dal contesto in cui servono per ottenere il valore di qualcosa, pertanto hanno soltanto un significato letterale nell'ambito della trasformazione. Ecco cosa si ottiene:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[italian,english]{babel}
\begin{document}
            

\section{Relazione introduttiva su XML}
        

11/11/2011



XML sta per Extensible Markup Language.    bla bla bla...
Perché,... così,... perciò,... sarà...

Bla, bla, bla....

Pinco Pallino



\end{document}

Il file che si ottiene utilizza la codifica UTF-8, cosa che consente di evitare l'uso di comandi particolari per rappresentare le lettere accentate, pertanto si è reso necessario l'utilizzo di un «pacchetto» adatto allo scopo (\usepackage[utf8]{inputenc}). Tuttavia rimangono da risolvere altri problemi legati a caratteri che non possono essere inseriti letteralmente, come per esempio nel caso di %, che per LaTeX costituisce l'inizio di un commento. Per questo occorrerebbe inserire nel DTD la dichiarazione di una serie di entità generali, che poi devono essere usate nel sorgente XML.

Infine, si noti che, per semplicità, nella trasformazione viene ignorato completamente il linguaggio, ovvero l'attributo lang dell'elemento relazione.

451.7.2   Trasformazione in un sorgente HTML

Per la trasformazione in un sorgente HTML si deve utilizzare un foglio di stile XSLT che elabora il risultato in modalità HTML, avendo cura, possibilmente, di predisporre anche la dichiarazione del DTD:

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:output
        method="html"
        doctype-public="ISO/IEC 15445:2000//DTD HTML//EN"
        encoding="ISO-8859-1" />
    <xsl:template match="/">
        <xsl:element name="HTML">
            <xsl:attribute name="LANG">
                <xsl:value-of select="relazione/@lang" />
            </xsl:attribute>
            <HEAD>
            <TITLE><xsl:value-of select="relazione/titolo" /></TITLE>
            <xsl:text disable-output-escaping="yes">
<![CDATA[<STYLE TYPE="text/css">
<!--
BODY {
    background-color: rgb(255, 255, 255)
}
H1 {
    text-align:       right;
    color:            rgb(230, 100, 180)
}

P.paragrafo {
    width:            auto;
    text-align:       left
}
P.data {
    text-align:       left;
    font-weight:      bold
}
P.firma {
    width:            auto;
    text-align:       left
-->
</STYLE>]]>
            </xsl:text>
            </HEAD>
            <BODY>
            <xsl:apply-templates />
            </BODY>
        </xsl:element>
    </xsl:template>
    <xsl:template match="titolo">
        <H1><xsl:apply-templates /></H1>
    </xsl:template>
    <xsl:template match="data">
        <P CLASS="data"><xsl:apply-templates /></P>
    </xsl:template>
    <xsl:template match="paragrafo">
        <P CLASS="paragrafo"><xsl:apply-templates /></P>
    </xsl:template>
    <xsl:template match="firma">
        <P CLASS="firma"><xsl:apply-templates /></P>
    </xsl:template>
</xsl:stylesheet>

Questa volta il foglio di stile XSLT è molto più articolato, anche perché incorpora la dichiarazione di alcuni stili CSS. Ecco il risultato che si ottiene; si osservi che il file viene generato usando la codifica ISO-8859-1:

<!DOCTYPE HTML PUBLIC "ISO/IEC 15445:2000//DTD HTML//EN">
<HTML LANG="it">
<HEAD>
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<TITLE>Relazione introduttiva su XML</TITLE>
<STYLE TYPE="text/css">
<!--
BODY {
    background-color: rgb(255, 255, 255)
}
H1 {
    text-align:       right;
    color:            rgb(230, 100, 180)
}

P.paragrafo {
    width:            auto;
    text-align:       left
}
P.data {
    text-align:       left;
    font-weight:      bold
}
P.firma {
    width:            auto;
    text-align:       left
-->
</STYLE>
            </HEAD>
<BODY>
<H1>Relazione introduttiva su XML</H1>

<P CLASS="data">11/11/2011</P>



<P CLASS="paragrafo">XML sta per Extensible Markup Language.    bla bla bla...
Perch&eacute;,... cos&igrave;,... perci&ograve;,... sar&agrave;...</P>

<P CLASS="paragrafo">Bla, bla, bla....</P>

<P CLASS="firma">Pinco Pallino</P>


</BODY>
</HTML>

451.7.3   Trasformazione in un sorgente XHTML

Per la trasformazione in un sorgente XHTML si deve utilizzare un foglio di stile XSLT che elabora il risultato in modalità XML:

<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output
        method="xml"
        encoding="UTF-8" />
    <xsl:template match="/">
        <xsl:element name="html">
            <xsl:attribute name="xml:lang">
                <xsl:value-of select="relazione/@lang" />
            </xsl:attribute>
            <head>
            <title><xsl:value-of select="relazione/titolo" /></title>
            <xsl:text disable-output-escaping="yes">
<![CDATA[<style type="text/css">
<!--
body {
    background-color: rgb(255, 255, 255)
}
h1 {
    text-align:       right;
    color:            rgb(230, 100, 180)
}

p.paragrafo {
    width:            auto;
    text-align:       left
}
p.data {
    text-align:       left;
    font-weight:      bold
}
p.firma {
    width:            auto;
    text-align:       left
-->
</style>]]>
            </xsl:text>
            </head>
            <body>
            <xsl:apply-templates />
            </body>
        </xsl:element>
    </xsl:template>
    <xsl:template match="titolo">
        <h1><xsl:apply-templates /></h1>
    </xsl:template>
    <xsl:template match="data">
        <p class="data"><xsl:apply-templates /></p>
    </xsl:template>
    <xsl:template match="paragrafo">
        <p class="paragrafo"><xsl:apply-templates /></p>
    </xsl:template>
    <xsl:template match="firma">
        <p class="firma"><xsl:apply-templates /></p>
    </xsl:template>
</xsl:stylesheet>

Il risultato che si ottiene manca di alcuni incolonnamenti che nelle altre situazioni venivano mantenuti. Per ovviare all'inconveniente, si può provare ad aggiungere l'attributo indent="yes" nell'elemento xsl:output:

<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output
        method="xml"
        indent="yes"
        encoding="UTF-8" />
    ...

Ecco il risultato, incolonnato, che si può ottenere:

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="it">
<head>
<title>Relazione introduttiva su XML</title>
<style type="text/css">
<!--
body {
    background-color: rgb(255, 255, 255)
}
h1 {
    text-align:       right;
    color:            rgb(230, 100, 180)
}

p.paragrafo {
    width:            auto;
    text-align:       left
}
p.data {
    text-align:       left;
    font-weight:      bold
}
p.firma {
    width:            auto;
    text-align:       left
-->
</style>
            </head>
<body>
<h1>Relazione introduttiva su XML</h1>

<p class="data">11/11/2011</p>



<p class="paragrafo">XML sta per Extensible Markup Language.    bla bla bla...
Perché,... così,... perciò,... sarà...</p>

<p class="paragrafo">Bla, bla, bla....</p>

<p class="firma">Pinco Pallino</p>


</body>
</html>

Si ricorda che in questo caso la codifica del file generato è UTF-8, inoltre, si fa notare che nel foglio di stile XSLT appare un dominio applicativo predefinito, allo scopo di riportarlo nel file XHTML di destinazione.

451.8   Riferimenti

Appunti di informatica libera 2007.02 --- Copyright © 2000-2007 Daniele Giacomini -- <daniele (ad) swlibero·org>


1) Xalan   software libero con licenza speciale


Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome introduzione_ai_fogli_di_stile_xslt.htm

[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico]

Valid ISO-HTML!

CSS validator!