XPath
# XPath

In informatica XPath è un linguaggio, parte della famiglia XML, che permette di individuare i nodi all'interno di un documento XML. Le espressioni XPath, a differenza delle espressioni XML, non servono a identificare la struttura di un documento, bensì a localizzarne con precisione i nodi.

XPath è nato originariamente dall'esigenza di fornire una sintassi e un comportamento comune fra XPointer e XSL; solo successivamente è stato adottato dagli sviluppatori come metodo di interrogazione dei dati in formato XML. La versione 1.0 di XPath è diventata uno standard W3C il 16 novembre 1999.

## Notazione

Il tipo più comune di espressione XPath (e quella che ha dato origine al suo nome) è la path expression. Una path expression è scritta come una sequenza di passi per raggiungere un nodo XML, partendo dal nodo corrente (percorso "relativo"). In alternativa è possibile utilizzare dei percorsi "assoluti" utilizzando come riferimento la radice del documento. Gli elementi sono separati dal carattere '/'. Ogni elemento ha tre componenti:

* Axis Specifier
* Node test
* Predicato

Sono state definite due notazioni:

* Sintassi abbreviata, compatta, che permette la realizzazione di costrutti intuitivi e facilmente realizzabili;
* Sintassi completa, più complessa, che contiene maggiori opzioni, in grado di specificare con più particolarità gli elementi.

### Sintassi abbreviata

La notazione abbreviata permette molte differenti sintassi per i casi comuni. L'XPath più semplice ha una forma del tipo:

* /A/B/C

che seleziona gli elementi di C che sono figli degli elementi B che sono figli dell'elemento A che rappresenta la radice del documento XML. La sintassi XPath è stata progettata per imitare la sintassi del URI (Uniform Resource Identifier) e quella usata per indicare i file o le directory nei file system.

Le espressioni più complesse possono essere costruite specificando un Axis differente da un semplice nome o predicato, che può essere scritto fra parentesi quadre dopo tutta l'espressione. Per esempio:

* A//B/*[1]

seleziona il primo elemento ("[1]"), figlio di B, indipendentemente dal suo nome, e dal numero di nodi che intercorrono tra A e B (//). Da notare che l'espressione non inizia con "/", quindi A è un nodo del contesto corrente.

### Sintassi espansa

Nella sintassi completa, i due esempi qui sopra sarebbero scritti:

* /child::A/child::B/child::C
* child::A/descendant-or-self::B/child::node[1]

In questo caso, ad ogni punto del XPath, l'Axis (per esempio child o descendant-or-self) è specificato esplicitamente, seguito da :: ed ancora seguito dal test del nodo, come A o node degli esempi sopra citati.

## Axis

L'Axis indica il senso di percorrenza dell'albero del documento XML. Gli Axis disponibili, nella sintassi completa ed abbreviata, sono:

### child

    default, non specificato nella sintassi abbreviata

### descendant

    non disponibile nella sintassi abbreviata

### ancestor

    non disponibile nella sintassi abbreviata

### ancestor-or-self

    non disponibile nella sintassi abbreviata

### following

    non disponibile nella sintassi abbreviata

### preceding

    non disponibile nella sintassi abbreviata

### following-sibling

    non disponibile nella sintassi abbreviata

### preceding-sibling

    non disponibile nella sintassi abbreviata

### namespace

    non disponibile nella sintassi abbreviata

Ad esempio, usando la seguente sintassi abbreviata, //a/@href si seleziona un attributo denominato href in un qualunque elemento a dell'albero del documento. L'Axis self è più comunemente usato per riferirsi al nodo attualmente selezionato. Per esempio, h3[.='See also'] seleziona un elemento denominato h3 nel contesto corrente, il cui testo è uguale a "See also".

## Node Test

I node test possono controllare nomi specifici di nodi o espressioni più generali. Nel caso di un documento XML in cui il prefisso del namespace gs è stato definito, //gs:enquiry troverà tutti i nodi enquiry di quel namespace.

Altri node test sono:

### comment

    trova un nodo di commento XML, per esempio <!-- Commento -->

### text

    trova un nodo di tipo testo, per esempio hello in <k>hello</k>

### processing-instruction

    trova istruzioni di processamento XML come <?php echo $a;?>. In questo caso ('php').

### node

    trova il nodo.

## Predicati

Espressioni di qualunque entità possono essere indicate fra parentesi quadre, le quali dovranno essere soddisfatte affinché il nodo possa essere preso in considerazione. Ad esempio //a[@href='help.php'], che abbinerà un elemento con un attributo href di cui il valore è help.php. Non c'è limite al numero di predicati e non devono essere limitati all'ultimo elemento di un'espressione XPath. Possono anche essere annidati. I percorsi specificati nei predicati faranno riferimento al contesto del relativo punto (cioè quello immediatamente prima del test del nodo).

//a[@href='help.php'][../div/@class='header']/@target selezionerà il valore dell'attributo target di un elemento a, se l'elemento ha un attributo href il cui valore è help.php e se il parent è un elemento div che ha un attributo class di valore header

## Funzioni ed operatori

XPath 1.0 definisce quattro tipi di dati: node-set (insiemi di nodi senza ordine intrinseco), stringhe, numeri e booleani.

Gli operatori disponibili sono:

* Operatori "/", "//" e [...] usati nelle espressioni del percorso, come precedentemente descritto.
* Un operatore di unione, "|", che forma l'unione di due node-set.
* Operatori booleani "and" e "or" e la funzione "not".
* Operatori aritmetici "+", "-", "*", "div" e "mod".
* Operatori di confronto "=", "!=", "<", ">", "<=", ">=".

La function library include:

* Funzioni per manipolare stringhe: concat, substring, contains, substring-before, substring-after, translate, normalize-space, string-length
* Funzioni per manipolare numeri: sum, round, floor, ceiling
* Funzioni per accedere alle proprietà dei nodi: name, local-name, namespace-uri
* Funzioni per accedere a informazioni del contesto del nodo: position, last
* Funzioni per la conversione dei tipi: string, number, boolean

Alcune delle funzioni più comuni sono dettagliate successivamente. Per una descrizione completa, si veda il documento di riferimento del W3C

### Funzioni su i nodi

**position**


    restituisce un numero che rappresenta la posizione di questo nodo rispetto ai relativi fratelli dal XPath a questo punto.

**count(node-set)**


    restituisce il numero di nodi che corrispondono alla relativa richiesta

### Funzioni per la manipolazione di stringhe

**string(object?)**


    converte ognuno dei quattro tipi di dati di XPath in una stringa. L'argomento può essere un XPath, nel qual caso i nodi abbinati sono convertiti in stringa.

**concat(string, string, string*)**


    concatena tutte le stringhe.

**contains(s1, s2)**


    restituisce true se s1 contiene s2.

**normalize-space(string?)**


    tutti i whitespace all'inizio e alla fine vengono rimossi e tutte le sequenze di whitespace sono sostituite da un singolo spazio. È molto utile quando l'XML originale dev'essere ben formattato, in grado di rendere ulteriormente fidata elaborazione della stringa.

### Funzioni booleane

**not(boolean)**


    nega tutta l'espressione booleana.

### Funzioni numeriche

**sum(node-set)**


    Converte i valori della stringa di tutti i nodi trovati, in numeri, quindi restituisce la somma di questi numeri.

Le espressioni possono essere generate usando gli operatori: =, !=, <=, <, >= e >. Le espressioni booleane possono essere unite con le parentesi e combinate con operatori booleani and, or e not. I calcoli numerici possono usare *, +, -, div e mod. Le stringhe possono consistere di tutti i caratteri di Unicode.

All'interno o all'esterno dei predicati, interi node-set possono essere uniti usando il carattere | ("pipe").

v[x or y] | w[z] restituirà un singolo node-set con tutti gli elementi di v che hanno come figli elementi y o x, insieme a tutti gli elementi di w che hanno figli z, trovati nel contesto corrente.

//item[@price > 2*@discount] seleziona gli item di cui l'attributo price è maggiore del doppio del valore dell'attributo discount.

## Esempi pratici

Analizziamo ora un semplice documento XML per capire meglio come accedere ai dati in esso contenuti.

### /listautenti/account//telefoni/*

    restituisce la lista di tutti i nodi all'interno del nodo telefoni, in questo caso fisso, cellulare e fax.

### /listautenti/account//indirizzo/..

    restituisce tutti i nodi che contengono un nodo indirizzo al loro interno, l'impiego dell'Axis // fa sì che vengano individuati anche nodi di livelli differenti purché all'interno di account.
