Linguaggi e tecnologie per il Web
Corso di Laurea in Ingegneria Informatica e Automatica
Sapienza Università di Roma
a.a. 2015/2016

XML

Parte 4:
XML Schema

Luigi Dragone, Riccardo Rosati


Sommario

  1. Limitazioni dei DTD
  2. Introduzione a XML Schema
  3. Costrutti di base
  4. Costrutti avanzati
  5. Data binding

Limitazioni dei DTD

I DTD sono il meccanismo "nativo" di XML per la definizione della struttura dei documenti

Essendo incentrati sui documenti sono poco adatti alla definizione di contenuti fortemente strutturati

I DTD possono essere utilizzati efficacemente per lo scambio di informazioni tra utenti, ma non tra sistemi automatici in quanto non consentono di stabilire con precisione il "tipo" delle informazioni. Storicamente i linguaggi a marcatura nascono come annotazione dei documenti testuali, ed è solo con la diffusione di XML che sono stati adoperati estensivamente per la rapresentazione delle informazioni


Limitazioni dei DTD (2)

La specifica di un DTD non è un documento XML. Ad es.:

<!ELEMENT e (#PCDATA)>

non è una produzione XML ben formata

I meccanismi di estensione e modularizzazione dei DTD sono estremamente limitati (definizioni esterne, entità parametriche)

I DTD non sono completamente compatibili con i namespace

I DTD non permettono di stabilire vincoli di chiave ed integrità referenziale, con l'eccezione degli attributi ID ed IDREF.


Introduzione a XML Schema

XML Schema è un'applicazione XML finalizzata alla definizione della struttura dei documenti XML, compito già svolto dai DTD, in modo più preciso e modulare rispetto a quanto permesso da questi ultimi.

XML Schema prevede la descrizione della struttura di un documento con un secondo documento XML (detto schema)

Analogamente a quanto avviene con i DTD è possibile validare un documento rispetto al proprio schema

Gli schemi XML prevedono la possibilità di creare dei modelli dati fortemente tipati (come linguaggi di programmazione tipo C, Java o linguaggi di specifica tipo DDL SQL) e sono compatibili con i namespace


Introduzione a XML Schema (2)

Gli schemi XML non sono sostitutivi dei DTD, ma i due sistemi devono essere utilizzati in concomitanza (ad es., in XML Schema non è possibile definire le entità)
In generale per i documenti scambiati tra utenti è preferibile utilizzare ancora i DTD, negli altri casi (ad es., strutture dati o basi di dati) gli schemi

L'impiego degli schemi in fase di validazione è molto più dispendioso, in termini di risorse computazionali, rispetto ai DTD (validare solo quando necessario)

Gli schemi XML possono essere utilizzati per il data binding

XML Schema: W3C Recommendation del 2/5/2001


Costrutti di base - Documento semplice

Definizione di un documento contenente un solo elemento di tipo testuale.

<?xml version="1.0"?>
<E>Hello</E>

Costrutti di base - Documento semplice (2)

Lo schema associato è:

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="E" type="xsd:string"/>
</xsd:schema>

Il tag element permette di definire un elemento del documento specificandone nome e tipo.
Nella definizione di uno schema l'elemento associato alla radice del documento (top-level element) è il primo dichiarato.


Costrutti di base - Documento semplice (3)

Per associare un documento (ovvero un'istanza di schema) al proprio schema si utilizzano degli attributi associati al namespace XSI (XML Schema Instance) sul root element, ad es:

<?xml version="1.0"?>
<E xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema.xsd">
Hello
</E>

Costrutti di base -Tipi semplici e complessi

In XML Schema si associa agli elementi un tipo (analogamente a quanto avviene nella definizione delle strutture dati dei LdP) che può essere semplice o complesso:

Un tipo complesso viene definito con il tag complexType


Costrutti di base - Tipi semplici

A differenza dei DTD è possibile specificare il tipo degli elementi semplici.
All'interno dei documenti XML tali elementi sono rappresentati comunque come stringhe, tuttavia è possibile restringere il campo delle stringhe valide (ad es., solo quelle che rappresentano numeri in virgola mobile, oppure numeri interi positivi, oppure date, oppure...).

I tipi semplici supportati sono:

Le precisioni dei tipi dato sono quelle di Java.

Costrutti di base - Esempio d'uso dei tipi semplici

<xsd:element name="NOME" type="xsd:string"/>
<xsd:element name="CDL" type="xsd:string"/>
<xsd:element name="DURATA" type="xsd:duration"/>
<xsd:element name="INIZIO" type="xsd:date"/>
<xsd:element name="ARGOMENTO" type="xsd:string"/>
<xsd:element name="PROGETTO" type="xsd:string"/>
<xsd:element name="CREDITI" type="xsd:nonNegativeInteger"/>

Costrutti di base -Estensione dei tipi semplici

Il sistema dei tipi può essere esteso mediante un meccanismo di ereditarientà imponendo restrizioni sui tipi derivati (ad es., mediante espressioni regolari).


Costrutti di base - Esempio di definizione di un tipo complesso

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="CORSO" type="TipoCorso"/>
<xsd:complexType name="TipoCorso">
<xsd:sequence>
<xsd:element name="NOME" type="xsd:string"/>
<xsd:element name="DOCENTE" type="xsd:string"/>
<xsd:element name="TUTOR" type="xsd:string"/>
<xsd:element name="CDL" type="xsd:string"/>
<xsd:element name="DURATA" type="xsd:string"/>
<xsd:element name="ARGOMENTO" type="xsd:string"/>
<xsd:element name="PROGETTO" type="xsd:string"/>
<xsd:element name="CREDITI" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

Costrutti di base - Esempio di definizione di un tipo complesso (2)

Il documento è formato da un elemento associato al tag CORSO di tipo complesso TipoCorso che contiene una sequenza di elementi di tipo stringa. La definizione DTD "equivalente" sarebbe stata:

<!ELEMENT CORSO (NOME, DOCENTE, TUTOR, CDL, DURATA, ARGOMENTO, PROGETTO, CREDITI)>

Un'istanza del precedente schema è:

<CORSO>
<NOME>Progetto di Linguaggi e Traduttori</NOME>
<DOCENTE>Riccardo Rosati</DOCENTE>
<TUTOR>Luigi Dragone</TUTOR>
<CDL>Ing. Informatica</CDL>
...
<CORSO>

Costrutti di base - Cardinalità degli elementi

Analogamente all'impiego delle espressioni regolari per la definizione del content model degli elementi, anche in XML Schema è possibile stabilire le cardinalità minime e massime dei vari elementi con l'uso degli attributi minOccurs e maxOccursche possono assumere un qualasiasi valore numerico intero >=0 oppure  unbounded per indicare un numero illimitato.

Se un elemento è opzionale allora il numero minimo di occorrenze è 0.


Costrutti di base - Esempio di cardinalità degli elementi

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="CORSO" type="TipoCorso"/>
<xsd:complexType name="TipoCorso">
<xsd:sequence>
<xsd:element name="NOME" type="xsd:string"/>
<xsd:element name="DOCENTE" type="xsd:string"/>
<xsd:element name="TUTOR" type="xsd:string"
minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="CDL" type="xsd:string"/>
<xsd:element name="DURATA" type="xsd:string"/>
<xsd:element name="ARGOMENTO" type="xsd:string"
minOccurs="1" maxOccurs="unbounded"/>
<xsd:element name="PROGETTO" type="xsd:string"
minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="CREDITI" type="xsd:string"
minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

Costrutti di base - Esempio di cardinalità degli elementi (2)

<CORSO>
<NOME>Linguaggi e tecnologie per il Web</NOME>
<DOCENTE>Riccardo Rosati</DOCENTE>
<TUTOR>Riccardo Rosati</TUTOR>
<CDL>Ing. Informatica</CDL>
<DURATA>60 ore</DURATA>
<ARGOMENTO>Parsing</ARGOMENTO>
<ARGOMENTO>HTML</ARGOMENTO>
<ARGOMENTO>XML</ARGOMENTO>
<ARGOMENTO>Programmazione Web lato client</ARGOMENTO>
<CREDITI>6</CREDITI>
<CORSO>

Costrutti di base - Tipi complessi con solo contenuto testuale

Per definire elementi a contenuto testuale, ci sono due casi:

  1. l'elemento da dichiarare non contiene attributi. In questo caso è sufficiente l'utilizzo di tipi semplici, come spiegato in precedenza;
  2. l'elemento da dichiarare può contenere attributi. In quesrto caso è necessario l'uso di un tipo complesso.

Esempio: dichiarazione di un elemento <a> contenente un testo di tipo intero e un attributo <attr> di tipo stringa:

<xsd:element name="a">
  <xsd:complexType>
    <xsd:simpleContent>
      <xsd:extension base="xsd:integer">
        <xsd:attribute name="attr" type="xsd:string" />
      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>
</xsd:element> 

Costrutti di base - Tipi complessi a contenuto misto

In XML Schema è possibile definire tipi a contenuto misto, ovvero contenenti sia parti testuali che altri elementi (e in modo più potente rispetto al mixed content model della DTD).

Esempio di dichiarazione di elemento <a> contenente sia parti testuali l'elemento <b>:

<xsd:element name="a">
  <xsd:complexType mixed="true">
    <xsd:element name="b" type="tipo1"/>
  </xsd:complexType>
</xsd:element> 

Esempio di dichiarazione di elemento <a> contenente sia parti testuali che gli elementi <b>, <c>, <d>:

<xsd:element name="a">
  <xsd:complexType mixed="true">
    <xsd:sequence>
      <xsd:element name="b" type="tipo1"/>
      <xsd:element name="c" type="tipo2"/>
      <xsd:element name="d" type="tipo1"/>
    </xsd:sequence>
  </xsd:complexType>
</xsd:element> 

Costrutti di base - Tipi complessi con contenuto vuoto

In XML Schema è possibile dichiarare elementi a contenuto vuoto (analogamente al content model EMPTY della DTD).

Esempio di dichiarazione di un elemento <a> vuoto (e senza attributi):
<xsd:element name="a">
  <xsd:complexType/>
</xsd:element>
Esempio di dichiarazione di un elemento <a> vuoto con un attributo attr di tipo intero positivo:
<xsd:element name="a">
  <xsd:complexType>
    <xsd:attribute name="attr" type="xsd:positiveInteger"/>
  </xsd:complexType>
</xsd:element>

Costrutti di base - Composizione di tipi complessi

Un elemento incluso in un tipo complesso può essere a sua volta associato ad un tipo complesso.

In tal modo i tipi possono essere composti, inoltre le definizione di un tipo può essere condivisa tra più elementi (anche se appartenenti a tipi diversi).

Una funzionalità di questo tipo può essere ottenuta con i DTD mediante l'impiego delle entità parametriche, ma risulta di difficile applicabilità.


Costrutti di base - Esempio di composizione di tipi complessi

Ad esempio il docente e gli eventuali tutori possono avere un nominativo ed un recapito.

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="CORSO" type="TipoCorso"/>
<xsd:complexType name="TipoPersona">
<xsd:sequence>
<xsd:element name="NOMINATIVO" type="xsd:string"/>
<xsd:element name="RECAPITO" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="TipoCorso">
<xsd:sequence>
<xsd:element name="NOME" type="xsd:string"/>
<xsd:element name="DOCENTE" type="TipoPersona"/>
<xsd:element name="TUTOR" type="TipoPersona"
minOccurs="0" maxOccurs="unbounded"/>
...
</xsd:sequence>
</xsd:complexType>
</xsd:schema>


Costrutti di base - Esempio di composizione di tipi complessi (2)

<CORSO>
...
<TUTOR>
<NOMINATIVO>Luigi Dragone</NOMINATIVO>
<RECAPITO>dragone@dis.uniroma1.it</RECAPITO>
</TUTOR>
...
</CORSO>

Costrutti di base - Tipi anonimi

Il tipo di un elemento può essere dichiarato all'interno all'elemento stesso (anonymous type), in tale caso la definizione non può essere condivisa.

Si tratta di un caso analogo all'uso delle classi anonime in Java.


Costrutti di base - Esempio d'uso di tipi anonimi

Ad esempio, il nominativo è suddiviso in nome e cognome:

<xsd:complexType name="TipoPersona">
<xsd:sequence>
<xsd:element name="NOMINATIVO">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="NOME" type="xsd:string"/>
<xsd:element name="COGNOME" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="RECAPITO" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>


Costrutti di base - Esempio d'uso di tipi anonimi (2)

<CORSO>
...
<TUTOR>
<NOMINATIVO><NOME>Luigi</NOME><COGNOME>Dragone</COGNOME></NOMINATIVO>
<RECAPITO>dragone@dis.uniroma1.it</RECAPITO>
</TUTOR>
...
</CORSO>

Costrutti di base - Modalità di composizione di tipi complessi

Il raggruppamento degli elementi all'interno della definizione di un tipo può avvenire in 3 modalità


Costrutti di base - Modalità di composizione di tipi complessi (2)

L'impiego dell'elemento all permette di specificare la presenza di un insieme di elementi indipendentemente dall'ordine. Gli elementi devono essere specificati con cardinalità massime e minime ristrette ai soli valori 0 ed 1.

Ad esempio, nel nominativo di una persona non è rilevante l'ordine del nome e del cognome:

<xsd:complexType name="TipoNominativo">
<xsd:all>
<xsd:element name="NOME" type="xsd:string"
minOccurs="1" maxOccurs="1"/>
<xsd:element name="COGNOME" type="xsd:string"
minOccurs="1" maxOccurs="1"/>
</xsd:all>
</xsd:complexType>


Costrutti di base - Modalità di composizione di tipi complessi (3)

<CORSO>
...
<TUTOR>
<NOMINATIVO><COGNOME>Dragone</COGNOME><NOME>Luigi</NOME></NOMINATIVO>
<RECAPITO>dragone@dis.uniroma1.it</RECAPITO>
</TUTOR>
...
</CORSO>

Costrutti di base - Modalità di composizione di tipi complessi (4)

Le scelte alternative possono essere combinate con le sequenze, analogamente a quanto avviene nei content model dei DTD, e specificare un intervallo di cardinalità ammissibili (ripetizioni).

<xsd:complexType name="TipoOrario">
<xsd:sequence>
<xsd:element name="DURATA" type="xsd:string"/>
<xsd:choice minOccurs="1" maxOccurs="unbounded">
<xsd:element name="LEZIONE" type="TipoLezione"/>
<xsd:element name="ESERCITAZIONE" type="TipoEsercitazione"/>
<xsd:element name="SEMINARIO" type="TipoSeminario"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>

Costrutti di base - Riferimenti ad elementi

Nel caso in cui lo stesso elemento può comparire all'interno di più elementi, è possibile usare l'attributo ref di <xsd:element>. Usando tale attributo al posto dell'attributo name, si fa riferimento alla dichiarazione dell'elemento il cui nome è il valore dell'attributo ref.

Ad esempio, il seguente frammento di schema stabilisce che l'elemento <a> compare nel content model degli elementi <b>, <c>, <d>, senza ripetere più volte la dichiarazione dell'elemento <a>:

  <xsd:element name="a">
    <xsd:complexType>
      ...
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="b">
    <xsd:complexType>
      <xsd:element ref="a">      
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="c">
    <xsd:complexType>
      <xsd:element ref="a">      
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="d">
    <xsd:complexType>
      <xsd:element ref="a">      
    </xsd:complexType>
  </xsd:element>

Costrutti di base - Attributi

La definizione dei tipi complessi ammette la possibilità di specificare i relativi attributi. Analogamente agli elementi anche gli attributi sono fortemente tipati ed è possibile specificare l'obbligatorietà oppure il valore predefinito.

<xsd:complexType name="TipoCorso">
<xsd:sequence>
<xsd:element name="NOME" type="xsd:string"/>
...
</xsd:sequence>
<xsd:attribute name="codice" type="xsd:string" use="required"/>
<xsd:attribute name="homePage" type="xsd:uriReference"/>
</xsd:complexType>
Possono essere definiti anche gruppi di attributi condivisi da più tipi/elementi.

Costrutti di base - Namespace

A differenza dei DTD, gli schemi sono compatibili con i namespace.

L'elemento schema possiede un attributo (targetNamespace) che specifica l'URI del namespace associato agli elementi in corso di definizione. Si deve specificare che gli elementi appartengono a tale namespace, mentre gli attributi in genere non sono associati a nessun namespace.

<?xml version="1.0"?>
<xsd:schema
xmlns="urn:dis.uniroma1.it:corso"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xsd:targetNamespace="urn:dis.uniroma1.it:corso"
xsd:elementFormDefault="qualified"
xsd:attributeFormDefault="unqualified">
<xsd:element name="CORSO" type="TipoCorso"/>
...
</xsd:schema>

Costrutti di base - Namespace (2)

L'impiego dei namespace richiede l'uso di un diverso costrutto per referenziare lo schema

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<corso:CORSO xmlns:corso="urn:dis.uniroma1.it:corso"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:dis.uniroma1.it:corso http://www.dis.uniroma.it/schema/corso.xsd">
...
</corso:CORSO>

L'URI del namespace è indipendente da quella dello schema. Mentre la prima non deve essere mai risolta (ovvero convertita in un indirizzo reale), la seconda deve puntare ad un'istanza del documento contentente lo schema. Si può associare anche ad uno schema un'indirizzo "virtuale" mediante un'URN, in tale caso il parser deve possedere una copia interna dello schema in questione, analogamente a quanto fatto dagli attuali browser web per il DTD di HTML.


Costrutti avanzati - Vincoli d'integrità

Una delle principali limitazioni dei DTD risiede nella gestione dei vincoli di unicità e di integrità referenziale.


Il meccanismo basato sull'impiego di attributi di tipo ID ed IDREF è estremamente limitato, in quanto l'unicità degli elementi non dipende dai valori propri, ma da un identificatore esterno.


Ad es.: non è possibile stabile che una persona sia identificata univocamente dal proprio none e cognome



Costrutti avanzati - Vincoli d'integrità (2)

Le basi dati permettono di definitire vincoli di più sofisticati. XML Schema introduce dei costrutti analoghi anche per XML basati sull'impiego di espressioni XPath.


Costrutti avanzati - Vincoli d'integrità (3)

I vincoli sono validi nell'ambito di dichiarazione (ad es., singolo elemento o intero documento) e sono caratterizzati da:

NB: I vincoli d'integrità sono associati agli elementi non ai tipi.


Costrutti avanzati - Vincoli d'integrità (4)

Rispetto al meccanismo standard di XML:

NB: La verifica dei vincoli d'integrità può essere estremamente onerosa, pertanto devono essere usati con accortezza


Costrutti avanzati - Ereditarietà

Analogamente a quanto avviente nei LdP OO, anche in XML Schema è possibile utilizzare l'ereditarietà tra i tipi complessi come strumento di modularizzazione

Un tipo può essere dichiarato final o abstract se non può essere ulteriormente derivato, oppure se non può essere istanziato direttamente

A differenza dei comuni linguaggi OO in XML Schema la derivazione può essere di due tipi:
Estensione
il sotto-tipo aggiunge nuove proprietà (ad es., attributi) al super-tipo;
Restrizione
il sotto-tipo elimina delle proprietà del super-tipo.

Costrutti avanzati - Composizione di schemi

Gli schemi XML possono essere composti mediante un meccanismo di inclusione/importazione che facilita la creazione di librerie di tipi ed accresce la modularità delle applicazioni

Sono previsti due meccanismi di composizione degli schemi:
Inclusione
(elemento include) di schemi che definiscono tipi all'interno dello stesso namespace dello schema includente
Importazione
(elemento import) di schemi che definiscono tipi in qualsiasi namespace

Data binding

L'uso degli schemi permette di gestire più facilmente il problema dell'associazione di strutture dati tipiche dei LdP (in particolare OO) ed i documenti XML. Tale problema viene denominato data binding. Il problema è diventato particolarmente rilevante non tanto per l'uso dei DB XML, quanto per l'impiego di XML come veicolo dati per i web service (serializzazione su socket).

In genere il problema della serializzazione e deserializzazione di strutture dati in XML viene trattato sfruttando apposite API (ad es., DOM e SAX)

Esistono degli strumenti che partendono da una specifica (schema XML oppure un diagramma delle classi) sono in grado di gestire automaticamente il problema della serializzazione da e verso XML.

In particolare gli strumenti guidati da XML producono delle classi che rappresentano i data object definiti dal documento (ad es., un complex type corrisponde ad una classe, mentre un elemento ad un riferimento piuttosto che ad un attributo).


Data binding (2)

Le maggiori difficoltà si incontrano quando sia la struttura XML che quella OO sono fissate ed è necessario costruire un adattatore. Non esiste una tecnica generale capace di risolvere tutti i problemi di ristrutturazione (a parte XSLT e sviluppo di adattatori ad-hoc), anche se gli strumenti possiedono un elevato livello di configurabilità del binding.

Tra gli strumenti disponbili per Java abbiamo:


Riferimenti

XML Schema Part 0: Primer W3C Recommendation 2 May 2001

XML Schema Part 1: Structures W3C Recommendation 2 May 2001

XML Schema Part 2: Datatypes W3C Recommendation 2 May 2001