- Famiglia di linguaggi XML: introduzione
- Sintassi dei NameSpace(Spazio dei Nomi)
- Dtd: Document Type Definition
- XML Schema: elementi e struttura
- XML Schema: Tipi di Dato
- XML Schema: Dichiarazione di tipi
- XML Schema: Integrazione con i namespace
- Presentazione di XML con CSS
- XSL: eXtensible Stylesheet Language
- XPath
- XSLT
- XSL-FO
Utilizzando queste semplici ed essenziali regole l'utente ha la possibilità di creare un nuovo linguaggio definendo i tag e gli attributi più appropriati a memorizzare l'informazione che si vuole trattare. Inoltre XML favorisce l'interoperabilità in quanto è un formato testuale, quindi facilmente trasferibile ed elaborabile su differenti piattaforme hardware e software. Una caratteristica fondamentale di XML è quella di occuparsi del contenuto dell'informazione e non la sua rappresentazione. La modalità di rappresentazione dell'informazione può essere scelta in un secondo momento e, partendo dallo stesso file XML, possiamo rappresentare l'informazione contenuta al suo interno in differenti modi, come ad esempio in HTML, XHTML, SVG, etc. Come esempio vediamo adesso di memorizzare in formato xml le informazioni relative ad una rubrica. Tipicamente in una rubrica, sono conservati alcuni dati (quali ad esempio nome, cognome, indirizzo, numero di telefono) riguardanti una determinata persona e tutto questo in XML può essere espresso con:
<?xml version="1.0"?> <rubrica> <persona> <nome>Mario</nome> <cognome>Rossi</cognome> <indirizzo> <via>via bianchi 1</via> <cap>00000</cap> <citta>Roma</citta> <email>m.rossi@tin.it</email> </indirizzo> <telefono> <telefono_fisso>123456</telefono_fisso> <cellulare>987656412</cellulare> </telefono> </persona> </rubrica>
In questo esempio abbiamo descritto in formato XML le informazioni relative ad una rubrica, andando a creare gli opportuni tag ed annidandoli in modo tale da rappresentare la struttura dati che avevamo in mente.
Proprio a causa delle caratteristiche descritte, XML ha incontrato molto successo come formato per lo scambio di dati tra applicazioni differenti.
Affinché due applicazioni possano scambiarsi dei dati in formato XML è necessario però che queste conoscano come viene strutturata l'informazione all'interno del file, ovvero quali sono e come sono chiamati i tag e gli attributi che costituiscono il file XML.
Per questo scopo sono state sviluppate alcune tecnologie quali XML Namespace, Dtd e XML Schema.
Sintassi dei NameSpace(Spazio dei Nomi)
XML Namespace nasce con lo scopo di evitare possibili ambiguità tra i nomi degli elementi che fanno parte di un linguaggio basato su XML, visto che utilizzando i Namespace siamo in grado di identificare univocamente i nomi dei tag e degli attributi.Un XML Namespace è un insieme di nomi, utilizzato per definire gli elementi e gli attributi di un linguaggio XML, a cui viene associato un URI (Universal Resource Identifier) di riferimento tramite il quale identificare in maniera assoluta il namespace. Un URI (Universal Resource Identifier) è una stringa di caratteri che definisce il nome di una risorsa sul web ed è per definizione unica. A questo insieme di nomi viene associato un prefisso che utilizzato in abbinata con il nome dell'elemento, permette di riferire univocamente tutti gli elementi.
Come esempio vediamo di definire un namespace per l'insieme di elementi utilizzati per descrivere la rubrica.
<?xml version="1.0"?> <mia_rubrica:rubrica xmlns:mia_rubrica="http://indirizzo_del_sito/mia_rubrica_ns"> <mia_rubrica:persona> <mia_rubrica:nome>Mario</mia_rubrica:nome> <mia_rubrica:cognome>Rossi</mia_rubrica:cognome> <mia_rubrica:indirizzo> <mia_rubrica:via>via bianchi 1</mia_rubrica:via> <mia_rubrica:cap>00000</mia_rubrica:cap> <mia_rubrica:citta>Roma</mia_rubrica:citta> <mia_rubrica:emali>m.rossi@tin.it</mia_rubrica:email> </mia_rubrica:indirizzo> <mia_rubrica:telefono> <mia_rubrica:telefono_fisso>123456</mia_rubrica:telefono_fisso> <mia_rubrica:cellulare>987656412</mia_rubrica:cellulare> </mia_rubrica:telefono> </mia_rubrica:persona> </mia_rubrica:rubrica>
Attraverso l'attributo xmlns (inserito nel primo tag del nostro file) definiamo l'URI di riferimento associato al nostro namespace e gli assegniamo un prefisso (mia_rubrica) che sarà utilizzato in abbinata con il nome dell'elemento per identificare in maniera univoca gli elementi del nostro file.
In un documento XML si fa riferimento ad un namespace utilizzando un attributo speciale (xmlns) associato al root element, come nel seguente esempio:
<articolo xmlns="http://www.dominio.it/xml/articolo">
Questo indica che l'elemento articolo ed i suoi sottoelementi utilizzano i nomi definiti nel namespace identificato dall'identificatore http://www.dominio.it/xml/articolo.
L'identificatore di un namespace può essere rappresentato da una qualsiasi stringa, purché sia univoca. Proprio per garantirne l'univocità, è prassi ormai consolidata utilizzare un URI (Uniform Resource Identifier) come identificatore.
È bene evidenziare che non è necessario che l'indirizzo specificato come identificatore di namespace corrisponda ad un file pubblicato sul Web. Esso è utilizzato semplicemente come identificatore ed il parser non accederà al Web per verificare l'esistenza dell'URL.
Per quanto riguarda la descrizione della struttura di un file XML, esistono due tecnologie: Dtd e XML Schema.
Dtd: Document Type Definition
Document Type Definition (Dtd) è un linguaggio utilizzato per definire la struttura di un file XML ed è storicamente il primo metodo utilizzato per tale scopo. È caratterizzato da una sintassi complessa, difficilmente estendibile e totalmente estranea al mondo XML, ma molto facile da usare.
Per vedere un esempio di Dtd proviamo a definire la struttura del nostro file XML che descrive la rubrica.
<!DOCTYPE rubrica [ <!ELEMENT rubrica (persona)> <!ELEMENT persona (nome, cognome, indirizzo, telefono)> <!ELEMENT nome (#PCDATA)> <!ELEMENT cognome (#PCDATA)> <!ELEMENT nome (#PCDATA)> <!ELEMENT indirizzo (via, cap, citta, email)> <!ELEMENT via (#PCDATA)> <!ELEMENT cap (#PCDATA)> <!ELEMENT citta (#PCDATA)> <!ELEMENT email (#PCDATA)> <!ELEMENT telefono (telefono_fisso, cellulare)> <!ELEMENT telefono_fisso (#PCDATA)> <!ELEMENT cellulare (#PCDATA)> ]>
Da un punto di vista cronologico, il primo approccio per la definizione di grammatiche per documenti XML è rappresentato dai Document Type Definition (DTD).
Un Dtd è un documento che descrive i tag utilizzabili in un documento XML, la loro reciproca relazione nei confronti della struttura del documento e altre informazioni sugli attributi di ciascun tag.
La sintassi di un Dtd si basa principalmente sulla presenza di due dichiarazioni: <!ELEMENT> e <!ATTLIST>. La prima definisce gli elementi utilizzabili nel documento e la struttura del documento stesso, la seconda definisce la lista di attributi per ciascun elemento. Ad esempio, la dichiarazione
<!ELEMENT articolo(paragrafo+)>
indica che l'elemento <articolo>
ha come sottoelemento uno o più
elementi <paragrafo>. Il carattere '+', dopo il nome del sottoelemento,
indica il relativo numero di occorrenze.
Un insieme di caratteri speciali ha appunto lo scopo di indicare il numero di occorrenze di un elemento. In particolare:
+
indica che l'elemento è presente una o più volte*
indica che l'elemento è presente zero o più volte?
indica che l'elemento è presente zero o una sola volta
Per esempio, la definizione
<!ELEMENT paragrafo(immagine*, testo+)>
indica che l'elemento <paragrafo>
contiene la sequenza di elementi
<immagine>
e <testo>
. L'elemento <immagine>
può essere presente zero o
più volte, mentre <testo> deve essere presente almeno una volta.
Per la definizione dei tag che non contengono sottoelementi dobbiamo
distinguere il caso dei tag vuoti dai tag che racchiudono testo. Nel
caso di tag vuoto, come accade per <immagine>
, la definizione è
<!ELEMENT immagine EMPTY>
Nel caso di elementi che racchiudono testo abbiamo una definizione analoga alla seguente:
<!ELEMENT testo (#PCDATA)>
Esiste la possibilità di definire elementi il cui contenuto non è definito a priori, possono cioè essere vuoti o contenere altri elementi senza vincoli particolari. Per definire questo tipo di elementi si utilizza la seguente dichiarazione:
<!ELEMENT elemento ANY>
Per la definizione degli attributi di ciascun tag facciamo uso della dichiarazione <!ATTLIST>. Ad esempio, la dichiarazione:
<!ATTLIST articolo titolo CDATA #REQUIRED>
indica che l'elemento <articolo>
prevede un attributo titolo che può
avere come valore una qualsiasi combinazione di caratteri (CDATA).
L'indicazione #REQUIRED indica che la
presenza dell'attributo è obbligatoria. Valori alternativi a #REQUIRED
sono:
-
#IMPLIED
Indica che l'attributo è opzionale -
#FIXED valore
Indica che il valore dell'attributo è fisso ed equivale al valore specificato
Se un attributo prevede valori alternativi predefiniti è necessario
specificarli al posto di CDATA, come accade per l'attributo tipo del tag
<paragrafo>
<!ATTLIST paragrafo
titolo CDATA #REQUIRED
tipo (abstract|bibliografia|note) #IMPLIED
>
In questo caso vengono definiti due attributi per l'elemento <paragrafo> facendo seguire alla definizione del primo attributo (titolo) quella del secondo(tipo). L'attributo tipo, opzionale, può assumere uno tra i valori abstract, bibliografia o note.
Il seguente codice riporta il Dtd completo per un documento che descrive un articolo:
<!ELEMENT articolo(paragrafo+)> <!ELEMENT paragrafo (immagine*, testo+, codice*)> <!ELEMENT immagine EMPTY> <!ELEMENT testo (#PCDATA)> <!ELEMENT codice (#PCDATA)> <!ATTLIST articolo titolo CDATA #REQUIRED> <!ATTLIST paragrafo titolo CDATA #IMPLIED tipo (abstract|bibliografia|note) #IMPLIED > <!ATTLIST immagine file CDATA #REQUIRED>
XML Schema: elementi e struttura
Utilizzando i Dtd, quindi, abbiamo un maggior controllo sulla struttura e sull'uso dei tag in un documento XML, evitando che la libertà nella definizione dei tag possa far perdere il controllo sui contenuti.
Tuttavia l'uso dei Dtd per definire la grammatica di un linguaggio di markup non sempre è del tutto soddisfacente. A parte il fatto che la sintassi utilizzata per definire un Dtd non segue le regole stesse di XML, i Dtd non consentono di specificare un tipo di dato per il valore degli attributi, né di specificare il numero minimo o massimo di occorrenze di un tag in un documento o altre caratteristiche che in determinati contesti consentirebbero di ottenere un controllo ancora più accurato sulla validità di un documento XML.
Queste limitazioni hanno spinto alla definizione di approcci alternativi per definire grammatiche per documenti XML. tra questi approcci il più noto è XML Schema.
Per ovviare alle limitazioni della Dtd è nato XML Schema, ovvero un linguaggio, basato su XML, per definire la struttura di un documento XML.
XML Schema è uno strumento molto più potente di Dtd per descrivere la struttura di un file XML in quanto è più espandibile, permette di ottenere una migliore caratterizzazione dei tipi di dati e ha una sintassi basata su XML, quindi possiamo utilizzare gli strumenti XML per lavorare con gli Schema.
La struttura del nostro esempio Rubrica, espressa con un XML Schema, diventa:
<?xml version="1.0"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:element name="rubrica" type="tipo_rubrica"/> <xsd:complexType name="tipo_rubrica"> <xsd:sequence> <xsd:element name="persona" type="tipo_persona"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="tipo_persona"> <xsd:sequence> <xsd:element name="nome" type="xsd:string"/> <xsd:element name="cognome" type="xsd:string"/> <xsd:element name="indirizzo" type="tipo_indirizzo"/> <xsd:element name="telefono" type="tipo_telefono"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="tipo_indirizzo"> <xsd:sequence> <xsd:element name="via" type="xsd:string"/> <xsd:element name="cap" type="xsd:decimal"/> <xsd:element name="citta" type="xsd:string"/> <xsd:element name="email" type="xsd:string"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="tipo_telefono"> <xsd:sequence> <xsd:element name="telefono_fisso" type="xsd:decimal"/> <xsd:element name="cellulare" type="xsd:decimal"/> </xsd:sequence> </xsd:complexType> </xsd:schema>
Analogamente ad un Dtd, un XML Schema è una descrizione formale di una grammatica per un linguaggio di markup basato su XML. L'approccio basato sui Dtd ci consente di specificare la struttura del nostro documento XML e di ciascun tag utilizzabile al suo interno con una precisione a prima vista accettabile.
Tuttavia, se abbiamo bisogno di un maggiore controllo sugli elementi che possono trovarsi all'interno di uno specifico tipo di documenti XML, i Dtd non risultano più sufficienti.
Ad esempio, i Dtd non mettono a disposizione un meccanismo immediato per indicare che un elemento può contenere al massimo un numero predefinito di sottoelementi, né è possibile specificare che un attributo può assumere valori di un certo tipo di dato, ad esempio valori numerici.
A differenza di un Dtd, che utilizza una propria sintassi specifica, un XML Schema utilizza la stessa sintassi XML per definire la grammatica di un linguaggio di markup. La cosa può sembrare paradossale, ma è invece indice dell'estrema flessibilità di XML.
Quindi uno XML Schema è un documento XML che descrive la grammatica di un linguaggio XML utilizzando un linguaggio di markup specifico. In quanto documento XML, uno XML Schema ha un root element che contiene tutte le regole di definizione della grammatica.
La struttura generale di uno schema XML è la seguente:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
... Definizione della grammatica ...
</xs:schema>
L'elemento root del documento è rappresentato dal tag <xs:schema>. Esso indica al parser che in questo documento saranno utilizzati dei tag definiti dal namespace standard del W3C.
Vedremo successivamente più in dettaglio cosa sono i namespace e come possiamo utilizzarli e definirli. Per il momento ci basti sapere che essi rappresentano un meccanismo per identificare tag appartenenti ad una specifica grammatica. Nel nostro caso questi tag speciali sono caratterizzati dal prefisso xs:.
XML Schema prevede il tag <xs:element> per la definizione degli elementi utilizzabili in un documento XML, specificando nell'attributo name il nome del relativo tag. All'interno di ciascun tag <xs:element> possiamo indicare il tipo di dato dell'elemento e possiamo definire gli eventuali attributi.
Ad esempio, la seguente definizione specifica l'elemento testo che può contenere soltanto stringhe:
<xs:element name="testo" type="xs:string" />
Questa dichiarazione corrisponde alla seguente dichiarazione Dtd:
<!ELEMENT testo (#PCDATA)>
Ma per comprendere meglio ed apprezzare la potenza degli XML Schema occorre analizzare il concetto di tipo di dato. Esistono due categorie di tipi di dato: semplici e complessi.
XML Schema: Tipi di Dato
XML Schema introduce il concetto di tipo di dato semplice per definire gli elementi che non possono contenere altri elementi e non prevedono attributi. Si possono usare tipi di dato semplici predefiniti oppure è possibile personalizzarli.
Sono previsti numerosi tipi di dato predefiniti, alcuni dei quali sono riportati nella seguente tabella:
Tipo di dato | Descrizione |
xs:string | Stringa di caratteri |
xs:integer | Numero intero |
xs:decimal | Numero decimale |
xs:boolean | Valore booleano |
xs:date | Data |
xs:time | Ora |
xs:uriReference | URL |
Ad esempio, la seguente dichiarazione:
<xs:element name="quantita" type="xs:integer" />
permette l'utilizzo dell'elemento quantita in un documento XML consentendo soltanto un contenuto di tipo intero. In altre parole, sarà considerato valido l'elemento <quantita>123</quantita> mentre non lo sarà l'elemento <quantita>uno</quantita>.
XML Schema prevede anche la possibilità di definire tipi di dato semplici personalizzati come derivazione di quelli predefiniti. Se, ad esempio, abbiamo bisogno di limitare il valore che può essere assegnato all'elemento <quantita> possiamo definirlo nel seguente modo:
<xs:element name="quantita" >
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="1" />
<xs:maxInclusive value="100" />
</xs:restriction>
</xs:simpleType>
</xs:element>
In altre parole, la dichiarazione indica che l'elemento <quantita> è di tipo semplice e prevede una restrizione sul tipo di dato intero predefinito accettando valori compresi tra 1 e 100.
I tipi di dato complessi si riferiscono ad elementi che possono contenere altri elementi e possono avere attributi. Definire un elemento di tipo complesso corrisponde a definire la relativa struttura.
Lo schema generale per la definizione di un elemento di tipo complesso è il seguente:
<xs:element name="NOME_ELEMENTO">
<xs:complexType>
... Definizione del tipo complesso ...
... Definizione degli attributi ...
</xs:complexType>
</xs:element>
Se l'elemento può contenere altri elementi possiamo definire la sequenza di elementi che possono stare al suo interno utilizzando uno dei costruttori di tipi complessi previsti:
- <xs:sequence> Consente di definire una sequenza ordinata di sottoelementi
- <xs:choice> Consente di definire un elenco di sottoelementi alternativi
- <xs:all> Consente di definire una sequenza non ordinata di sottoelementi
Per ciascuno di questi costruttori e per ciascun elemento è possibile definire il numero di occorrenze previste utilizzando gli attributi minOccurs e maxOccurs. Ad esempio, se l'elemento testo può essere presente una o infinite volte all'interno di un paragrafo possiamo esprimere questa condizione nel seguente modo:
<xs:element name="paragrafo">
<xs:complexType>
<xs:element name="testo" minOccurs="1"
maxOccurs="unbounded"/>
</xs:complexType>
</xs:element>
In questo caso il valore unbounded indica che non è stabilito un massimo numero di elementi testo che possono stare all'interno di un paragrafo.
La definizione della struttura di un elemento è ricorsiva, cioè contiene la definizione di ciascun elemento che può stare all'interno della struttura stessa.
Per gli elementi vuoti è prevista una definizione basata sul seguente schema:
<xs:element name="NOME_ELEMENTO">
<xs:complexType>
<xs:complexContent>
<xs:extension base="xs:anyType" />
... Definizione degli attributi ...
</xs:complexContent>
</xs:complexType>
</xs:element>
In altri termini, un elemento vuoto è considerato un elemento di tipo complesso il cui contenuto non si basa su nessun tipo predefinito.
La definizione degli attributi è basata sull'uso del tag <xs:attribute>, come nel seguente esempio:
<xs:attribute name="titolo" type="xs:string" use="required" />
L'attributo use consente di specificare alcune caratteristiche come la presenza obbligatoria (required) o un valore predefinito (default) in combinazione con l'attributo value. Ad esempio, la seguente definizione indica un attributo il cui valore di predefinito è test:
<xs:attribute name="titolo" type="xs:string" use="default" value="test" />
Bisogna tener presente che se non si specifica esplicitamente l'obbligatorietà dell'attributo, esso è considerato opzionale. Il seguente codice presenta uno XML Schema relativo al linguaggio di descrizione di articoli tecnici mostrato nei vari esempi.
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="articolo">
<xs:complexType>
<xs:sequence>
<xs:element name="paragrafo" maxOccurs="unbounded">
<xs:complexType>
<xs:all maxOccurs="unbounded">
<xs:element name="immagine" minOccurs="0">
<xs:complexType>
<xs:attribute name="file"
use="required">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="testo"/>
<xs:element name="codice" minOccurs="0"/>
</xs:all>
<xs:attribute name="titolo" type="xs:string"
use="optional"/>
<xs:attribute name="tipo" use="optional">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="abstract"/>
<xs:enumeration
value="bibliografia"/>
<xs:enumeration value="note"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="titolo" type="xs:string"
use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>
Questo XML Schema è equivalente al Dtd prima vista.
XML Schema: Dichiarazione di tipi
XML Schema prevede la possibilità di rendere modulare la definizione della struttura di un documento XML tramite la dichiarazione di tipi e di elementi.
Nel corso della creazione di uno schema XML possiamo analizzare ciascun sottoelemento significativamente complesso e fornire una definizione separata come elemento o come tipo di dato.
Questo contribuisce a fornire una struttura modulare allo schema, più ordinata, più comprensibile e semplice da modificare. Sfruttando la struttura modulare delle dichiarazioni, il contenuto di uno XML Schema diventa una sequenza di dichiarazioni di tipi ed elementi.
Possiamo definire un tipo complesso in base al seguente schema:
<xs:complexType name="nome_tipo">
...
</xs:complexType>
Il riferimento ad una dichiarazione di tipo viene fatta come se fosse un tipo predefinito, come mostrato nel seguente esempio:
<xs:element name="nome_elemento" type="nome_tipo" />
La possibilità di dichiarare elementi e tipi di dato implica l'esistenza di un ambito di visibilità o contesto dei componenti dichiarati. I componenti di uno schema dichiarati al livello massimo, cioè come sottoelementi diretti dell'elemento root, sono considerati dichiarati a livello globale e possono essere utilizzati nel resto dello schema.
Nella dichiarazione di un tipo complesso è possibile fare riferimento ad elementi già esistenti dichiarati a livello globale oppure si possono definire nuovi elementi. La definizione di nuovi elementi all'interno di una definizione di tipo o di elemento costituisce una dichiarazione a livello locale. Ciò vuol dire che l'utilizzo di questi elementi è limitato alla definizione del tipo complesso in cui sono dichiarati e non possono essere utilizzati in altri punti dello schema.
I nomi degli elementi devono essere univoci nel contesto in cui compaiono. Questo significa, però, che in contesti diversi possiamo avere elementi con lo stesso nome ma con struttura diversa senza rischio di conflitti.
Per fare un'analogia con i classici linguaggi di programmazione, le dichiarazioni globali e locali di componenti di uno schema corrispondono alle dichiarazioni di variabili globali e locali in un'applicazione.
Il seguente codice riporta lo XML Schema per un linguaggio di descrizione di articoli visto nel paragrafo precedente, riorganizzato alla luce della possibilità di definire tipi di dato.
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="articolo">
<xs:complexType>
<xs:sequence>
<xs:element name="paragrafo" type="paragrafoType"
maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="titolo" type="xs:string"
use="required"/>
</xs:complexType>
</xs:element>
<xs:complexType name="paragrafoType">
<xs:all maxOccurs="unbounded">
<xs:element name="immagine" type="immagineType"
minOccurs="0"/>
<xs:element name="testo"/>
<xs:element name="codice" minOccurs="0"/>
</xs:all>
<xs:attribute name="titolo" type="xs:string"
use="optional"/>
<xs:attribute name="tipo" use="optional">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="abstract"/>
<xs:enumeration value="bibliografia"/>
<xs:enumeration value="note"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
<xs:complexType name="immagineType">
<xs:attribute name="file" use="required">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:schema>
Come si può vedere, la leggibilità dello schema è molto maggiore rispetto alla prima versione. Inoltre, i tipi definiti a livello globale possono essere riutilizzati nel caso servisse modificare lo schema e quindi la struttura dei documenti XML risultanti.
XML Schema: Integrazione con i namespace
A partire da una grammatica definita tramite uno XML Schema, è possibile sfruttare un parser XML validante per verificare la validità di un documento XML. Il parser avrà bisogno, quindi, sia del documento XML da validare, sia dello schema XML rispetto a cui effettuare la validazione.
Ci sono diversi modi per fornire al parser informazioni sullo schema da utilizzare per la validazione.
Nell'ambito delle tecnologie XML, un XML Schema definisce implicitamente un namespace degli elementi e degli attributi che possono essere usati in un documento XML.
Se in un documento XML si utilizzano elementi definiti in schemi diversi abbiamo bisogno di un meccanismo che permetta di identificare ciascun namespace e il relativo XML Schema che lo definisce.
In un documento XML si fa riferimento ad un namespace utilizzando un attributo speciale (xmlns) associato al root element, come nel seguente esempio:
<articolo xmlns="http://www.dominio.it/xml/articolo">
Questo indica che l'elemento articolo ed i suoi sottoelementi utilizzano i nomi definiti nel namespace identificato dall'identificatore http://www.dominio.it/xml/articolo.
L'identificatore di un namespace può essere rappresentato da una qualsiasi stringa, purché sia univoca. Proprio per garantirne l'univocità, è prassi ormai consolidata utilizzare un URI (Uniform Resource Identifier) come identificatore.
È bene evidenziare che non è necessario che l'indirizzo specificato come identificatore di namespace corrisponda ad un file pubblicato sul Web. Esso è utilizzato semplicemente come identificatore ed il parser non accederà al Web per verificare l'esistenza dell'URL.
Per mettere in relazione un namespace con il relativo XML Schema occorre dichiararlo nel root element come nel seguente esempio:
<articolo
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.dominio.it/xml/articolo"
xmlns=
"http://www.dominio.it/xml/bibliografia"
xsi:schemaLocation=
"http://www.dominio.it/xml/articolo
articolo.xsd"
xsi:schemaLocation=
"http://www.dominio.it/xml/bibliografia
bibliografia.xsd"
>
L'attributo xmlns:xsi specifica la modalità con cui viene indicato il riferimento allo schema, mentre l'attributo xsi:schemaLocation indica il namespace ed il file in cui è definito il relativo XML Schema separati da uno spazio.
Eì possibile combinare più namespace facendo in modo che ciascun elemento utilizzato faccia riferimento al proprio namespace.
Occorre tener presente che quando si fa riferimento ad un namespace, questo riferimento vale per l'elemento corrente e per tutti gli elementi contenuti, a meno che non venga specificato un diverso namespace.
Il seguente esempio utilizza elementi tratti da due diversi namespace: uno relativo alla grammatica della struttura di un articolo e l'altro relativo alla grammatica di bibliografie:
<articolo
xmlns="http://www.dominio.it/xml/articolo" titolo="Guida
ad XML">
<paragrafo titolo="Introduzione">
<testo>
bla bla bla
</testo>
</paragrafo>
<paragrafo titolo="Bibliografia">
<bibliografia
xmlns=
quot;http://www.dominio.it/xml/bibliografia">
<autore>
Tizio
</autore>
<titolo>
Opera citata
</titolo>
<anno>
1999
</anno>
</bibliografia>
</paragrafo>
</articolo>
Riportare il riferimento ad un namespace per ogni elemento è di solito scomodo e rende di difficile lettura il documento XML. È possibile creare delle abbreviazioni per fare riferimento ai namespace.
Queste abbreviazioni sono costituite da caratteri alfanumerici seguiti da due punti (:) dichiarati nel root element ed utilizzati come prefissi dei nomi degli elementi. Il seguente esempio riporta il codice XML precedente facendo uso di questi prefissi:
<art:articolo titolo="Guida ad XML"
xmlns:art="http://www.dominio.it/xml/articolo"
xmlns:bibl=
"http://www.dominio.it/xml/bibliografia" >
<art:paragrafo titolo="Introduzione">
<art:testo>
bla bla bla
</art:testo>
</art:paragrafo>
<art:paragrafo titolo="Bibliografia">
<bibl:bibliografia>
<bibl:autore>
Tizio
</bibl:autore>
<bibl:titolo>
Opera citata
</bibl:titolo>
<bibl:anno>
1999
</bibl:anno>
</bibl:bibliografia>
</art:paragrafo>
</art:articolo>
Le dichiarazioni xmlns:art e xmlns:bibl assegnano i prefissi art: e bibl: ai relativi namespace e questi prefissi vengono utilizzati per ciascun elemento del documento XML.
Presentazione di XML con CSS
A differenza di HTML, che è un linguaggio specifico di strutturazione e presentazione di documenti, XML è più generale e non ha una semantica di presentazione. Non è previsto alcun meccanismo predefinito per visualizzare i vari elementi di un documento.
Ad esempio, un documento XML visualizzato in un browser appare generalmente così com'è, al massimo con una indentazione e una colorazione dei tag impostata dal browser.
Un metodo per gestire la presentazione del contenuto di un documento XML consiste nell'utilizzare i Cascading Style Sheets (CSS).
È possibile utilizzare i CSS in modo analogo a come si utilizzano con HTML. Per ciascun elemento del documento XML che vogliamo formattare occorre definire una regola secondo lo schema:
selettore { proprietà: valore; proprietà: valore; ... }
Il selettore specifica a quale elemento la regola deve essere applicata, mentre la parte racchiusa tra parentesi graffe elenca le caratteristiche da impostare e il relativo valore.
È opportuno evidenziare una importante differenza tra l'utilizzo dei CSS per formattare documenti HTML e il loro uso per i documenti XML. In HTML la maggior parte dei tag ha una formattazione predefinita e pertanto un foglio di stile CSS consente di ridefinire tali impostazioni.
In XML i tag non hanno alcun significato di formattazione, pertanto è necessario specificare tutto. Ad esempio, senza l'opportuna indicazione il testo contenuto nei diversi elementi di un documento XML verrebbe visualizzato come un'unica stringa.
Per strutturare visivamente il documento dobbiamo indicare la modalità di visualizzazione di ciascun elemento tramite la proprietà display di CSS. Ad esempio, per formattare l'elemento paragrafo di un articolo possiamo definire una regola come la seguente:
paragrafo {display: block; font-size: 12pt; text-align: left}
Generalmente un foglio di stile CSS da applicare ad un documento XML viene salvato in un file di testo con estensione .css (in realtà l'estensione usata è irrilevante). Nel documento XML possiamo quindi inserire un riferimento ad esso mediante unìapposita direttiva di elaborazione, come nel seguente esempio:
<?xml-stylesheet type="text/css" href="stile.css" ?>
Questa dichiarazione fa in modo che un browser abilitato applichi le impostazioni del foglio di stile CSS specificato al documento XML.
I fogli di stile CSS sono pensati principalmente per il Web e mancano pertanto di alcune caratteristiche che possono risultare utili in ambiti diversi. Ad esempio, per la presentazione su supporti cartacei occorrerebbero maggiori funzionalità per l'impaginazione. tra le principali limitazioni, non è prevista la possibilità di estrarre il valore degli attributi degli elementi in modo da poterli visualizzare.
Considerando il seguente esempio
<articolo titolo="Guida ad XML">
non abbiamo la possibilità di visualizzare il titolo dell'articolo che è stato espresso come attributo dell'elemento <articolo>. Questo costringerebbe a dover strutturare un documento XML in funzione della sua formattazione con CSS, in evidente contraddizione con lo stesso concetto di foglio di stile che tende a separare la definizione dei dati dalla sua presentazione.
Inoltre, non sempre un documento XML descrive qualcosa di visualizzabile con un browser. Ad esempio, è possibile definire un linguaggio XML per la descrizione di immagini o di ambienti virtuali. In questo caso i CSS non sono di alcun aiuto nella presentazione del documento.
Per risolvere questi problemi il W3C ha definito un'insieme di specifiche volte a gestire in maniera altamente flessibile la presentazione e la trasformazione di documenti XML: l'eXtensible Stylesheet Language (XSL).
XSL: eXtensible Stylesheet Language
L'eXtensible Stylesheet Language (XSL) è un insieme di tre linguaggi che forniscono gli strumenti per l'elaborazione e la presentazione di documenti XML in maniera molto flessibile.
La definizione di questa tecnologia si basa sull'osservazione del processo di presentazione di dati di qualsiasi natura. Infatti, in un tale processo possiamo individuare i seguenti meccanismi di base:
- un meccanismo per l'individuazione dei dati da presentare
- un meccanismo per il controllo dell'elaborazione dei dati e di come la presentazione deve essere effettuata
- un meccanismo per la definizione della formattazione da applicare ai dati per la presentazione vera e propria
A ciascuno di questi tre meccanismi, XSL associa uno specifico linguaggio:
- XPath consente di individuare gli elementi e gli attributi di un documento XML sui quali verranno applicate le operazioni necessarie per la presentazione dei dati
- XSLT (XSL transformation) consente di controllare le operazioni che rendono i dati presentabili
- XSL-FO (XSL Formatting Objects) definisce un insieme di tag di formattazione
Questa suddivisione dei compiti nel processo di presentazione è il punto di forza di XSL e ne garantisce la flessibilità. Infatti, questi tre linguaggi non sono strettamente dipendenti l'uno dall'altro.
Se, ad esempio, in una particolare applicazione ci rendiamo conto che XPath non soddisfa le nostre esigenze di ricerca di elementi in un documento XML, potremmo utilizzare linguaggio analogo (XQL, per citarne uno) ma senza modificare la presentazione dei caratteri.
Oppure potremmo decidere di non utilizzare affatto XSL-FO per formattare i dati di un documento XML e produrre direttamente codice HTML, o meglio XHTML, cioè la versione di HTML basata su XML.
La presentazione dei dati racchiusi in un documento XML è basata su due elementi:
- un documento che descrive come i dati devono essere elaborati per la presentazione, chiamato foglio di stile XSLT
- un componente software, chiamato processore XSLT, in grado di prendere in input un documento XML e un foglio di stile XSLT e di produrre in output i dati secondo il formato di presentazione prescelto (XSL-FO, XHTML, testo, ecc.)
La definizione di un foglio di stile XSLT è quindi il punto cruciale della presentazione dei dati XML. Le regole di trasformazione presenti in un foglio XSLT consentono di selezionare gli elementi di un documento XML e di gestirne la modalità di presentazione. Come abbiamo giù detto, nella definizione standard di XSLT la selezione degli elementi da presentare viene fatta tramite il linguaggio XPath.
XPath
Iniziamo con questo capitolo, la panoramica sulle tecnologie della
famiglia XML andando a parlare di XPath.
XPath è un linguaggio tramite il quale è possibile esprimere delle
espressioni per indirizzare parti di un documento XML. È un linguaggio
ideato per operare all'interno di altre tecnologie XML (di cui parleremo
nei capitolo successivi), quali XSL e XPointer, ed è caratterizzato dal
fatto di avere una sintassi non XML. In questo modo può essere meglio
utilizzato all'interno di URI o come valore di attributi di documenti
XML.
XPath opera su una rappresentazione logica del documento XML, che viene
modellato con una struttura ad albero ed XPath definisce una sintassi
per accedere ai nodi di tale albero.
Oltre a questo XPath mette a disposizione una serie di funzioni per la
manipolazione di stringhe, numeri e booleani, da utilizzare per operare
sui valori o sugli attributi dei nodi.
Le espressioni definite da XPath per accedere ai nodi dell'albero
prendono il nome di Location Path (percorsi di localizzazione).
La struttura un location path è la seguente:
axis::node-test[predicate].
La componente axis esprime la relazione di parentela tra il nodo
cercato ed il nodo corrente; la componente node-test specifica il tipo o
il nome del nodo da cercare; mentre predicate contiene zero o più filtri
(espressi tra parentesi quadre) per specificare delle condizioni più
selettive da applicare alla ricerca.
Le relazioni di parentela principali che possono essere contenute in
axis sono:
- ancestor: indica tutti i nodi antenati del nodo corrente, ovvero tutti i nodi che lo precedono nell'albero associato al documento XML;
- attribute: indica tutti gli attributi del nodo corrente;
- child: indica i nodi figli del nodo corrente;
- descendant: indica tutti i discendenti del nodo corrente, ovvero tutti i nodi che hanno seguono il nodo corrente nell'albero XML;
- parent: indica il nodo genitore del nodo corrente, ovvero quello che lo precede nell'albero;
- self: indica il nodo corrente.
Vediamo qualche esempio per capire meglio come utilizzare i Location Path per accedere agli elementi di un documento XML, utilizzando l'esempio della rubrica introdotto nel capitolo precedente, anche se con qualche piccola modifica.
<?xml version="1.0"?>
<rubrica>
<persona>
<nome>Mario</nome>
<cognome>Rossi</cognome>
<indirizzo>
<via>via bianchi 1</via>
<cap>00000</cap>
<citta>Roma</citta>
</indirizzo>
<telefono>
<telefono_fisso gestore="Abc">123456</telefono_fisso>
<telefono_cellulare gestore=
"Def">987656412</telefono_cellulare>
</telefono>
</persona>
</rubrica>
child::nome
Questa espressione seleziona tutti i nodo chiamati 'nome' che sono figli
del nodo corrente.
child::*
Seleziona tutti i nodi figli del nodo corrente.
attribute::gestore
Seleziona l'attributo di nome 'gestore' del nodo corrente.
descendant::cognome[cognome='Rossi']
Seleziona tutti i nodi chiamati 'cognome' tra i nodi discendenti del
nodo corrente, il cui valore è Rossi.
In XPath è possibile accedere ai nodi dell'albero utilizzando delle
espressioni abbreviate dei Location Path.
Le espressioni abbreviate, come suggerisce il nome stesso, sono una
versione semplificata e compatta dei Location Path ed offrono un
meccanismo più veloce, ma al tempo stesso meno potente per accedere ai
nodi dell'albero. Queste espressioni sono costituite da una lista di
nomi di elementi del documento XML, separati da uno slash(/), e tale
lista descrive il percorso per accedere all'elemento desiderato.
È un meccanismo molto simile a quello usato per identificare i file e le
directory nel filesystem. Ad esempio per indicare il file (chiamato
mio-file) memorizzato all'interno di una directory (chiamata
mia-directory) del vostro hard disk, utilizzate la seguente sintassi:
c:directory1file1.
Le espressioni abbreviate di XPath utilizzano un meccanismo
concettualmente simile: vediamo come, utilizzando il solito file XML
d'esempio.
/rubrica/persona/nome Questa espressione abbreviata permette di recuperare i nodi chiamati 'nome' indicando il percorso assoluto per raggiungere il nodo desiderato, attraverso una lista di nodi separata da slash.
//nome
Con il doppio slash ricerchiamo i nodi chiamati 'nome', in tutto il
documento, indipendentemente dalla loro posizione e dal loro livello
sull'albero associato al documento XML.
/rubrica//via
Ricerchiamo tutti i nodi chiamati 'via' a qualsiasi livello dell'albero
purchè contenuti all'interno del nodo chiamato 'rubrica'.
/rubrica/persona/*
Ricerca qualsiasi elemento figlio del nodo chiamato 'persona'.
//nome/@valuta
Ricerca l'attributo 'valuta' dell'elemento 'nome'. Anche all'interno
delle espressioni abbreviate possiamo inserire i predicati visti nel
caso dei Location Path. Ad esempio:
//persona[nome='Mario']
questa espressione ricerca tutti i nodi 'persona' che hanno il tag
'nome' il cui valore è Mario.
Come detto all'inizio del capitolo, XPath mette a disposizione anche delle funzioni per gestire i nodi, le stringhe, i numeri e i booleani. Vediamo adesso di elencare brevemente e schematicamente alcune funzioni principali:
- count(node-set): restituisce il numero di nodi contenuti nell'insieme di nodi passato come argomento della funzione;
- name(nodo): restituisce il nome di un nodo;
- position(): determina la posizione di un elemento all'interno di un insieme di nodi;
- last(): indica la posizione dell'ultimo nodo di un'insieme di nodi;
- id(valore): seleziona gli elementi in funzione del loro identificatore;
- concat(s1,...,sn): restituisce una stringa risultato della concatenazione delle stringhe specificate tra gli argomenti di una funzione;
- string(valore): converte il valore dell'argomento in una stringa;
- string-length(stringa): ritorna la lunghezza della stringa passata come parametro;
- substring(stringa,inizio,lunghezza): restituisce una sotto-stringa della stringa passata come argomento;
- ceiling(numero): arrotonda il numero per eccesso;
- floor(numero): arrotonda il numero per difetto;
- number(valore): converte il valore dell'argomento in un numero;
- sum(node-set): esprime la somma di un insieme di valori numerici contenuti in un insieme di nodi.
Come esempi di espressioni XPath che fanno uso di queste funzioni
consideriamo:
//persona[last()]
Questa espressione restituisce l'ultimo nodo 'persona' contenuto
all'interno del file XML.
//persona[position()= 3]
Restituisce il terzo nodo 'persona' contenuto all'interno del file XML.
count(/rubrica/persona)
Indica il il numero di nodi chiamati 'persona' contenuti all'interno del
documento XML.
XSLT
Una caratteristica fondamentale di XML è quella di occuparsi
esclusivamente della descrizione del contenuto dell'informazione e non
della sua rappresentazione.
Infatti i tag XML non esprimono in alcun modo come verrà visualizzato il
loro contenuto, cosa che invece accade in altri linguaggi basati su
marcatori, come HTML.
L'informazione contenuta in un file XML può essere visualizzata
definendo degli stili di rappresentazione, che, applicati al file XML,
saranno in grado di rappresentarne il contenuto nel modo desiderato.
In XML questo può essere fatto utilizzando XSL (eXtensible Stylesheet
Language). XSL è un linguaggio basato su XML per esprimere i fogli di
stile, ossia un documento contenente le regole per rappresentare
l'informazione. XSL è composto da due componenti: XSLT (eXtensible
Stylesheet Language transformation), che descriveremo in questo
capitolo, e XSL-FO (eXtensible Stylesheet Language - Formatting
Objects), che analizzeremo nel prossimo capitolo.
All'interno di XSL viene utilizzato XPath per la ricerca ed il
filtraggio dei contenuti del file XML.
XSLT è un linguaggio basato su XML che permette di definire delle
regole per trasformare un documento XML in un altro documento XML o in
un documento HTML. Utilizzando XSL possiamo ad esempio visualizzare il
contenuto di un documento XML in HTML, XHTML o SVG.
La trasformazione viene realizzata da un XSLT Processor che riceve come
input il file XML da trasformare, il file XSL con la definizione dello
stylesheet da applicare e produce come output il file trasformato. Un
file XSL è formato da una serie di template (modelli) che contengono le
regole di trasformazione dei tag del documento XML. Questi template
vengono applicati ai tag corrispondenti dal XSLT Processor in maniera
ricorsiva nel corso della trasformazione.
Come esempio vediamo di definire un file XSL per visualizzare un file
XML di esempio in una pagina HTML.
Il file XML di input è:
<?xml version="1.0"?>
<rubrica>
<persona>
<nome>Mario</nome>
<cognome>Rossi</cognome>
<indirizzo>
<via>via bianchi 1</via>
<cap>00000</cap>
<citta>Roma</citta>
</indirizzo>
<telefono>
<telefono_fisso>123456</telefono_fisso>
<telefono_cellulare>
987656412</telefono_cellulare>
</telefono>
</persona>
</rubrica>
Il file XSL con la definizione dello stile per la creazione del file HTML è:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/transform"
version="1.0">
<xsl:template match="/">
<html>
<head>
<title>Rubrica in versione HTML</title>
</head>
<body>
<h1>Rubrica</h1>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="persona">
<h2> <xsl:value-of select="cognome"/> <xsl:value-of
select="nome"/> </h2>
<ul>
<li>Via: <xsl:value-of select="./indirizzo/via"/></li>
<li>CAP: <xsl:value-of select="./indirizzo/cap"/></li>
<li>Citta': <xsl:value-of select="./indirizzo/citta"/></li>
<li>Telefono (fisso): <xsl:value-of
select="./telefono/telefono_fisso"/></li>
<li>Telefono (cellulare): <xsl:value-of
select="./telefono/telefono_cellulare"/></li>
</ul>
</xsl:template>
</xsl:stylesheet>
In un file XSL le regole di trasformazione sono contenute all'interno
degli elementi template e tramite l'attributo match possiamo
specificare, utilizzando la sintassi XPath, il tag a cui si riferiscono
queste regole. Nel nostro esempio il primo elemento template
contiene le regole di trasformazione dell'elemento root del file di
input (l'elemento <rubrica>); mentre il secondo definisce le regole per
la trasformazione degli elementi <persona>.
Il processore XSLT effettua il parsing del documento XML da trasformare
e, per ogni nodo incontrato, ricerca il template appropriato
all'interno del file XSL.
Quando il processore incontra il nodo root del documento XML applica il
primo template e quindi costruisce lo scheletro del file HTML.
Con l'elemento <xsl:apply-templates> si indica al processore XSLT di
analizzare i nodi figli del nodo corrente alla ricerca di altri
template da applicare.
Il risultato prodotto dalla trasformazione XSLT è il seguente:
<html>
<head>
<title>Rubrica in versione HTML</title>
</head>
<body>
<h1>Rubrica</h1>
<h2>Rossi Mario</h2>
<ul>
<li>Via: via bianchi 1</li>
<li>CAP: 00000</li>
<li>Citta': Roma</li>
<li>Telefono (fisso): 123456</li>
<li>Telefono (cellulare): 987656412</li>
</ul>
</body>
</html>
Lo stesso file XML può essere trasformato in un'immagine SVG utilizzando il seguente file XSL:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/transform"
version="1.0">
<xsl:template match="/">
<svg width="400" height="200">
<title>Rubrica in versione SVG</title>
<xsl:apply-templates/>
</svg>
</xsl:template>
<xsl:template match="persona">
<rect x="10" y="10" width="180" height="30" fill="lightblue"
stroke="blue" stroke-width="2"/>
<text x="20" y="30" font-family="times" font-width="20"
fill="black">
<xsl:value-of select="cognome"/> <xsl:value-of
select="nome"/>
</text>
<rect x="10" y="40" width="200" height="150" fill="white"
stroke="blue" stroke-width="2"/>
<text x="20" y="60" font-family="times" font-width="20" fill="blue">
Via: <xsl:value-of select="./indirizzo/via"/>
</text>
<text x="20" y="80" font-family="times" font-width="20" fill="blue">
CAP: <xsl:value-of select="./indirizzo/cap"/>
</text>
<text x="20" y="100" font-family="times" font-width="20"
fill="blue">
Citta': <xsl:value-of select="./indirizzo/citta"/>
</text>
<text x="20" y="120" font-family="times" font-width="20"
fill="blue">
Telefono (fisso): <xsl:value-of
select="./telefono/telefono_fisso"/>
</text>
<text x="20" y="140" font-family="times" font-width="20"
fill="blue">
Telefono (cellulare): <xsl:value-of
select="./telefono/telefono_cellulare"/>
</text>
</xsl:template>
</xsl:stylesheet>
Il risultato della trasformazione è il seguente:
<svg width="400" height="200">
<title>Rubrica in versione SVG</title>
<rect x="10" y="10" width="180" height="30" fill="lightblue"
stroke="blue" stroke-width="2"/>
<text x="20" y="30" font-family="times" font-width="20"
fill="black">Rossi Mario</text>
<rect x="10" y="40" width="200" height="150" fill="white"
stroke="blue" stroke-width="2"/>
<text x="20" y="60" font-family="times" font-width="20"
fill="blue">Via: via bianchi 1</text>
<text x="20" y="80" font-family="times" font-width="20"
fill="blue">CAP: 00000</text>
<text x="20" y="100" font-family="times" font-width="20"
fill="blue">Citta': Roma</text>
<text x="20" y="120" font-family="times" font-width="20"
fill="blue">Telefono (fisso): 123456</text>
<text x="20" y="140" font-family="times" font-width="20"
fill="blue">Telefono (cellulare): 987656412</text>
</svg>
XSLT è uno strumento grazie al quale possiamo decidere di visualizzare gli stessi dati contenuti in un file XML in differenti modi a seconda delle nostre esigenze ed il tutto in maniera assolutamente automatica.
XSL-FO
In questo capitolo andiamo ad analizzare la seconda componente di
XSL, XSL-FO.
XSL-Formatting Objects è un linguaggio, anch'esso basato su XML, per la
specifica di una semantica di formattazione dei contenuti di un
documento XML. All'interno di un documento XSL-FO possiamo definire le
regole di impaginazione delle informazioni che vogliamo visualizzare,
andando ad esprimere la posizione dei singoli contenuti nella pagina.
Grazie a XSL-FO possiamo produrre, ad esempio dei documenti PDF, RTF o
PS, rappresentanti il contenuto di un documento XML. Il documento XSL-FO
viene analizzato da un processore XSL-FO che si occupa di produrre il
documento di output, in base alle regole specificate nel documento di
input.
La struttura di un file XSL-FO è la seguente:
<?xml version="1.0"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<!--modello pagina-->
</fo:layout-master-set>
<fo:declarations>
<!--dichiarazioni globali-->
</fo:declarations>
<fo:page-sequence>
<!--contenuti pagine-->
</fo:page-sequence>
</fo:root>
All'interno dell'elemento <layout-master-set> vanno inserite le
regole di impaginazione per la pagina master, ovvero la pagina che
costituisce il modello per tutte le altre pagine del documento. Il
secondo elemento (<declarations>)contiene eventuali dichiarazioni
globali al file XSL-FO; mentre l'elemento <page-seguence> contiene la
definizione delle informazioni contenute nelle pagine che costituiranno
il documento finale.
Per cercare di capire meglio il funzionamento di XSL-FO vediamo di
analizzare il seguente documento di esempio:
<?xml version="1.0"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="PaginaA4"
page-height="29.7cm" page-width="21cm" margin-top="1.5cm"
margin-bottom="1.5cm" margin-left="2.5cm" margin-right="2.5cm">
<fo:region-body margin-top="1.8cm"/>
<fo:region-before extent="1.3cm"/>
<fo:region-after extent="1.3cm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="PaginaA4">
<fo:title>Esempio XSL-FO</fo:title>
<fo:static-content flow-name="xsl-region-before">
<fo:block text-align="end" font-size="8pt" font-family="times">
Esempio XSL-FO
</fo:block>
</fo:static-content>
<fo:static-content flow-name="xsl-region-after">
<fo:block text-align="end" font-size="8pt" font-family="times">
Pagina <fo:page-number/>
</fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block text-align="center" font-size="14pt" font-family="times"
color="blue">
Testo della prima pagina dell'esempio XSL-FO.
</fo:block>
<fo:block break-before="page" text-align="center" font-size="14pt"
font-family="times" color="green">
Testo della seconda pagina dell'esempio XSL-FO.
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
Come detto in precedenza, il modello della pagina master viene
definito con l'elemento <single-page-master>.
Nel nostro caso, al suo interno, abbiamo specificato le misure di un
foglio in formato A4 utilizzando gli attributi dell'elemento.
Inoltre abbiamo indicato anche la dimensione dell'intestazione (con
l'elemento <region-before>), la dimensione del piè di pagina (con
l'elemento <region-after>) e del contenuto della pagina (con l'elemento
<region-body>).
Una volta stabilito il modello della pagina andiamo a specificare il
contenuto delle pagine del nostro documento con l'elemento
<page-sequence>.
Gli elementi che troviamo al suo interno sono:
- <title>: permette di specificare il titolo del documento;
- <static-content>: indica le informazioni che verranno ripetute in ogni pagina;
- <flow>: elemento che contiene il contenuto delle pagine.
Nel nostro esempio abbiamo definito, in <static-content>,
l'intestazione delle pagine del documento contenente il titolo e il piè
di pagina con il numero di pagina, che viene calcolato in maniera
automatica grazie al tag <page-number>.
Nell'elemento <flow> abbiamo definito il contenuto delle due pagine che
costituiscono il nostro esempio.
Il risultato della trasformazione del documento di esempio da parte del
processore XSL-FO è il documento PDF mostrato in figura.
Se volessimo creare un documento XSL-FO in grado di visualizzare il contenuto di un documento XML allora sarebbe necessario applicare una prima trasformazione XSLT al file XML, in modo da produrre il file XSL-FO con le regole di impaginazione. Una volta prodotto questo documento saremmo in grado di utilizzare il processore XSL-FO per creare, ad esempio, un documento PDF contenente i dati del documento XML di partenza.