Nello capitolo dedicato ad "XLink" abbiamo visto come è affrontato in XML il problema del collegamento tra risorse. Ora andiamo invece ad analizzare un linguaggio che ci permette di avere una maggiore granularità nel collegamento tra risorse.
XML Pointer language (XPointer) è un linguaggio ideato per indirizzare parti di un documento XML. Con XPointer abbiamo uno strumento per indirizzare precisi punti o porzioni di un documento. Da notare che le parti di documento sono linkate senza che si debba andare a modificare il documento di destinazione, come avviene ad esempio in HTML.
Infatti se volessimo linkare un elemento all'interno di una pagina HTML, dovremmo "marcarlo" con un tag, come in questo esempio:
<a name="mio-link">parte link</a>
Fatto questo allora potremmo costruire un collegamento a quella scritta di esempio con il seguente link:
<a href="nome-di-un-dominio/esempio.html#mio-link">Collegamento</a>
Questo è un sistema poco pratico perchè impone di andare a modificare il documento di destinazione (cosa non sempre possibile), indicando tutti i punti verso i quali si vuole costruire un link.
XPointer ci permette di ovviare a questo problema e di specificare dei link a porzioni di un documento senza doverlo modificare. XPointer usa la sintassi XPath, con qualche estensione, per identificare le parti di documento da indirizzare.
Consideriamo il seguente file di esempio:
<?xml version="1.0"?>
<rubrica>
<persona>
<nome>Mario</nome>
<cognome ID="p1">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>
<persona>
<nome>Carlo</nome>
<cognome ID="p2">Bianchi</cognome>
<indirizzo>
<via>via rossi 1</via>
<cap>00000</cap>
<citta>Roma</citta>
</indirizzo>
<telefono>
<telefono_fisso>123456</telefono_fisso>
<telefono_cellulare>987656412</telefono_cellulare>
</telefono>
<persona>
<persona>
<nome>Giovanni</nome>
<cognome ID="p3">Verdi</cognome>
<indirizzo>
<via>via verdi 1</via>
<cap>00000</cap>
<citta>Roma</citta>
</indirizzo>
<telefono>
<telefono_fisso>2573698</telefono_fisso>
<telefono_cellulare>145278954</telefono_cellulare>
</telefono>
<persona>
</rubrica>
Basandoci su questo documento andiamo a considerare i seguenti esempi di espressioni XPointer:
http://nome-di-un-dominio/esempio-rubrica.xml#xpointer(/rubrica/persona[cognome='Rossi'])
Questa espressione XPointer permette di stabilire un link all'elemento <persona> (che contiene il tag <cognome> con valore pari a 'Rossi') contenuto nel file di esempio identificato dall'URI http://nome-di-un-dominio/esempio-rubrica.xml.
http://nome-di-un-dominio/esempio-rubrica.xml#xpointer(//persona[last()])
Stabilisce un link con l'ultimo elemento <persona> del nostro file di esempio.
http://nome-di-un-dominio/esempio-rubrica.xml#xpointer(/child::rubrica/child::persona/child::nome)
Crea un link con tutti gli elementi <nome> contenuti all'interno dei tag <persona> del nostro file di esempio.
Le funzioni origin(), here() e id()
Come emerge chiaramente dagli esempi appena visti, XPointer fa largo uso delle espressioni XPath (sia i location path che le loro espressioni abbreviate) per selezionare le parti di documento a cui collegarsi.
In XPointer però sono presenti anche delle estensioni alle espressioni XPath che mettono a disposizione delle funzioni per accedere più velocemente a certe parti del documento.
Queste estensioni sono: id(), here(), origin().
La funzione id() consente di selezionare l'elemento all'interno del documento XML, che ha l'attributo ID con valore pari al quello specificato come paramentro della funzione.
Ad esempio:
http://nome-di-un-dominio/esempio-rubrica.xml#xpointer(id("p1"))
Questa espressione crea un link con l'elemento del file di esempio con attributo ID pari a p1 (che nel nostro caso corrisponde all'elemento <cognome> con valore pari a 'Rossi') ed è del tutto equivalente all'uso della seguente espressione xpointer: http://nome-di-un-dominio/esempio-rubrica.xml#xpointer(//*[@ID='p1']).
Ovviamente la funzione id() può essere usata solamente se sono presenti degli elementi con attributo ID, nel documento a cui vogliamo collegarci.
La funzione here() restituisce un riferimento al nodo che contiene l'espressione XPointer. Questa funzione è molto utile nel caso di link all'interno dello stesso documento perchè facilita la costruzione di link ad elementi successivi o precedenti rispetto al nodo in considerazione. Ad esempio:
<rubrica>
<persona>
<nome>Mario</nome>
<cognome ID="p1">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>
<precedente xlink:type="simple" xlink:href="here()/../preceeding::persona[1]"/>
<successivo xlink:type="simple" xlink:href="here()/../following::persona[1]"/>
</persona>
<persona>
<nome>Carlo</nome>
<cognome ID="p2">Bianchi</cognome>
<indirizzo>
<via>via rossi 1</via>
<cap>00000</cap>
<citta>Roma</citta>
</indirizzo>
<telefono>
<telefono_fisso>123456</telefono_fisso>
<telefono_cellulare>987656412</telefono_cellulare>
</telefono>
<precedente xlink:type="simple" xlink:href="here()/../preceeding::persona[1]"/>
<successivo xlink:type="simple" xlink:href="here()/../following::persona[1]"/>
</persona>
<persona>
<nome>Giovanni</nome>
<cognome ID="p3">Verdi</cognome>
<indirizzo>
<via>via verdi 1</via>
<cap>00000</cap>
<citta>Roma</citta>
</indirizzo>
<telefono>
<telefono_fisso>2573698</telefono_fisso>
<telefono_cellulare>145278954</telefono_cellulare>
</telefono>
<precedente xlink:type="simple" xlink:href="here()/../preceeding::persona[1]"/>
<successivo xlink:type="simple" xlink:href="here()/../following::persona[1]"/>
<persona>
</rubrica>
In questo caso abbiamo inserito all'interno del nostro esempio due link XML, che utilizzando la funzione here(), costituiscono due collegamenti agli elementi <persona> precedenti e successivi rispetto all'elemento contenente il link.
La funzione origin() restituisce un riferimento alla sorgente del link. Questa, a differenza di here(), è molto utile nei casi di link tra risorse contenute in differenti file XML; infatti grazie a origin() possiamo ottenere un riferimento al documento XML dal quale è stato attivato il link.
Collegamenti all'interno dei singoli nodi
Fino ad adesso abbiamo visto come creare dei collegamenti ai singoli nodi contenuti all'interno di un documento XML.In XPointer però è possibile stabilire dei collegamenti anche alle informazioni contenute all'interno dei singoli nodi. Questo può essere molto utile nel caso di nodi XML che contengono al loro interno informazioni testuale non formattate XML.
Ad esempio considerando il nodo <nome>Mario</nome>, in XPointer è possibile creare un link, ad esempio a qualsiasi carattere contenuto all'inteno dell'elemento <nome>.
Per far questo XPointer mette a disposizione delle funzioni per analizzare le stringhe contenute nel nodo e determinare il punto preciso od intervalli di valori a cui vogliamo collegarci.
La prima funzione che descriveremo è string-range e permette di identificare un intervallo all'interno di un particolare nodo od insieme di nodi.
La sua sintassi è:
String-range(location-set, substring, index, length)
.
Il paramentro location-set identifica i nodi da analizzare; substring permette di specificare la sottostringa da ricercare; index e length indicano rispettivamente quali caratteri e quanti caratteri considerare, dopo la sottostringa trovata.
Ad esempio:
xpointer(string-range(/,"Bianchi",4,3)[position()=1])
Questa espressione stabilisce un link con la prima occorrenza della stringa 'Bianchi' contenuta all'interno del nostro file di esempio ed in particolare ricerca la sottostringa 'chi', identificata dagli ultimi due parametri della funzione string-range.
Le altre funzioni, presenti in XPointer per identificare gli intervalli o i loro estremi, sono:
- start-point(): indica il primo carattere della stringa trovata;
- end-point(): indica il primo carattere dopo il carattere finale della stringa trovata;
- range(): indentifica l'intero intervallo;
- range-inside(): indica l'intervallo contenuto all'interno di un elemento (escludendo però i tag iniziali e finali);
- range-to(): inserito alla fine di un location path, identifica la parte finale dell'intervallo.
Ad esempio:
http://nome-di-un-dominio/esempio-rubrica.xml#xpointer(start-point(string-range(id("p1"),"Rossi")))
Identifica il punto iniziale della stringa 'Rossi' contenuta all'interno dell'elemento con ID="p1".
http://nome-di-un-dominio/esempio-rubrica.xml#xpointer(//persona[position()=1]/range-to(//persona[last()]))
Questa espressiona seleziona tutto ciò che è contenuto tra il primo tag <persona> e l'ultimo tag </persona> contenuti nel nostro file d'esempio.
Conoscendo la struttura del documento verso il quale vogliamo costruire un link, XPointer ci permette di identificare una parte contando gli elementi figli, partendo dal nodo root fino ad arrivare all'elemento desiderato. Ad esempio:
http://nome-di-un-dominio/esempio-rubrica.xml#/1/3/1
http://nome-di-un-dominio/esempio-rubrica.xml#/1/3/2
I due esempi ci permettono di identificare il primo ed il secondo figlio del terzo figli del nodo root, che nel nostro esempio corrisponde agli elementi <nome>Giovanni</nome> e <cognome>Verdi</cognome>.
Potete trovare maggiori dettagli ed informazioni su XPointer andando a leggere la specifica del linguaggio all'indirizzo: http://www.w3.org/tr/xptr.