Tutorial XPath per principianti

Con la diffusione dell'XML come linguaggio di markup per lo scambio di dati indipendente dalla piattaforma, è cresciuta la necessità di uno standard che consenta ad applicazioni non basate su XML di interrogare questi documenti.

N.B.

L'Extensible Markup Language (XML) è un linguaggio di markup utilizzato per visualizzare dati strutturati gerarchicamente sotto forma di testo. L'XML è ugualmente leggibile sia per l'uomo che per le macchine e viene utilizzato, tra l'altro, nel World Wide Web per lo scambio di dati tra due sistemi informatici.

Gli standard corrispondenti per l'accesso programmatico ai documenti XML sono stati sviluppati dal Consorzio W3 con XQuery e XSLT e forniscono interfacce di programmazione che le applicazioni possono utilizzare per accedere, interrogare o trasformare documenti XML. Il prerequisito è uno standard che consente l'indirizzamento di elementi in documenti XML, ovvero il linguaggio XPath.

Vi presentiamo il modello di dati XPath (XDM) e la sintassi alla base delle espressioni XPath per localizzare gli elementi XML.

Che cos'è XPath?

L'XML Path Language (XPath) è un linguaggio di interrogazione per documenti XML, sviluppato dal consorzio W3. XPath fornisce agli utenti una sintassi non basata su XML che permette loro di indirizzare gli elementi di un documento XML in modo mirato.

Di norma, XPath è integrato in un linguaggio host, che consente di elaborare gli elementi XML indirizzati. XQuery, per esempio, è usato per interrogare elementi XML indirizzati da XPath. XSLT utilizza il linguaggio di interrogazione per trasformare i documenti XML.

  • XPath: navigazione in documenti XML
  • XQuery: interrogazioni su documenti XML
  • XSLT: trasformazione di documenti XML

Nella raccomandazione del W3C del 21 marzo 2017 è specificata la versione attuale di XPath 3.1.

N.B.

Nonostante l'ulteriore sviluppo, molti processori XSLT, browser web e applicazioni continuano a supportare soltanto lo standard XPath 1.0 del 1999.

Come funziona XPath?

XPath si basa su un modello di dati che interpreta i documenti XML come una sequenza di elementi disposti in una struttura ad albero. La struttura ad albero del modello di dati XPath è simile a quella del Document Object Model (DOM), che funge da interfaccia tra l'HTML e il JavaScript dinamico nel browser web.

La localizzazione degli elementi XML si basa sul sistema di directory Unix sotto forma di percorsi. I componenti di base di questi percorsi di localizzazione sono i nodi, gli assi, i test di nodo e i predicati.

Tipi di nodi

I singoli elementi di una struttura ad albero XPath sono chiamati nodi. I nodi sono ordinati sia in base alla sequenza del documento che all'annidamento degli elementi XML.

Il modello di dati XPath distingue sette tipi di nodi con funzioni diverse:

  • Nodo elemento (element node)
  • Nodo documento (root node) (in XPath 2.0 e versioni successive, precedentemente nodo radice)
  • Nodo attributo (attribute node)
  • Nodo testo (text node)
  • Nodo namespace (namespace node)
  • Nodo istruzione di elaborazione (processing instruction node)
  • Nodo commento (comment node)

Illustreremo i tipi di nodi del modello di dati XPath utilizzando un esempio. Il seguente documento XML viene utilizzato per lo scambio di dati nell'ambito di un ordine di libri e contiene tutti e sette i tipi di nodi.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Order SYSTEM "order.dtd">
<?xml-stylesheet type="text/css" href="style.css"?>

<!--That is a comment!-->

<order date="2019-02-01">
    <address xmlns:shipping="http://localhost/XML/delivery" xmlns:billing="http://localhost/XML/billing">
        <shipping:name>Ellen Adams</shipping:name>
        <shipping:street>123 Maple Street</shipping:street>
        <shipping:city>Mill Valley</shipping:city>
        <shipping:state>CA</shipping:state>
        <shipping:zip>10999</shipping:zip>
        <shipping:country>USA</shipping:country>
        <billing:name>Mary Adams</billing:name>
        <billing:street>8 Oak Avenue</billing:street>
        <billing:city>Old Town</billing:city>
        <billing:state>PA</billing:state>
        <billing:zip>95819</billing:zip>
        <billing:country>USA</billing:country>
    </address>
    <comment>Please use gift wrapping!</comment>
    <items>
        <book isbn="9781408845660">
            <title>Harry Potter and the Prisoner of Azkaban</title>
            <quantity>1</quantity>
            <priceus>22.94</priceus>
            <comment>Please confirm delivery date until Christmas.</comment>
        </book>
        <book isbn="9780544003415">
            <title>The Lord of the Rings</title>
            <quantity>1</quantity>
            <priceus>17.74</priceus>
        </book>
    </items>
</order>

Nodo elemento (element node)

Nella struttura ad albero del modello di dati XPath, ogni elemento del documento XML corrisponde a un nodo elemento. Fanno eccezione la dichiarazione XML e la definizione del tipo di documento all'inizio.

Dichiarazione XML:

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

Definizione del tipo di documento (DTD):

<!DOCTYPE Order SYSTEM "order.dtd">

I nodi elemento iniziano con un tag di apertura, terminano con un tag di chiusura e sono solitamente annidati l'uno nell'altro.

Il primo nodo elemento nella sequenza del documento è chiamato elemento radice.

Il documento XML mostrato sopra, per esempio, contiene l'elemento radice order, che funge da elemento genitore dei nodi elemento subordinati address, comment e items che contengono a loro volta altri nodi elemento come elementi figlio.

Nodo documento (document node)

I nodi documento formano le radici della struttura ad albero, che nel documento XML stesso non sono rappresentati né visivamente né testualmente. Si tratta di un nodo concettuale che contiene tutti gli altri elementi del documento. Gli elementi figlio del nodo documento sono l'elemento radice e, eventualmente, i nodi istruzione di elaborazione e commento.

Nodo attributo (attribute node)

Gli attributi di un elemento XML sono rappresentati come nodi attributo nel modello di dati XPath. Ogni nodo attributo è costituito da un identificatore e un relativo valore.

Nell'esempio di codice summenzionato, il primo nodo elemento book contiene il nodo attributo isbn con il valore 9781408845660.

<book isbn="9781408845660">

I nodi attributo sono considerati come appartenenti al nodo elemento, ma non come suoi elementi figlio.

Nodo testo (text node)

I dati di caratteri contenuti tra il tag di apertura e di chiusura di un nodo elemento sono chiamati nodi testo.

Nell'esempio di codice, ilnodo elemento title contiene il nodo testo Harry Potter and the Prisoner of Azkaban.

Harry Potter and the Prisoner of Azkaban

Nodo namespace

Nei documenti XML ben formati, tutti i nomi degli elementi e degli attributi utilizzati sono assegnati a uno spazio di nomi. L'assegnazione è di solito già stabilita in base alla definizione del tipo di documento all'inizio.

Se in un documento XML vengono utilizzati elementi o attributi con diversi namespace, il rispettivo spazio di nomi viene definito esplicitamente nel tag di apertura dell'elemento in questione mediante l'attributo xmlns o il prefisso xmlns. L'attributo xmlns si aspetta un valore Uniform Resource Identifier(URI), che specifica lo spazio di nomi a cui assegnare l'elemento corrispondente. L'assegnazione di uno spazio di nomi a un prefisso xmlns è disponibile per l'elemento e per tutti gli elementi figlio. Ogni namespace corrisponde a un nodo namespace nella struttura ad albero.

Nell'esempio di codice, sono stati definiti due namespace per l'elemento XML address: xmlns:shipping e xmlns:billing. Gli elementi figlio dell'elemento address hanno come prefisso la rispettiva assegnazione.

<address xmlns:shipping="http://localhost/XML/delivery" xmlns:billing="http://localhost/XML/ billing">
        <shipping:name>Ellen Adams</shipping:name>
        <shipping:street>123 Maple Street</shipping:street>
        <shipping:city>Mill Valley</shipping:city>
        <shipping:state>CA</shipping:state>
        <shipping:zip>10999</shipping:zip>
        <shipping:country>USA</shipping:country>
        <billing:name>Mary Adams</billing:name>
        <billing:street>8 Oak Avenue</billing:street>
        <billing:city>Old Town</billing:city>
        <billing:state>PA</billing:state>
        <billing:zip>95819</billing:zip>
        <billing:country>USA</billing:country>
    </address>

Il prefisso xmlns permette di assegnare in modo univoco elementi con lo stesso nome provenienti da diversi namespace. Ad esempio, l'elemento street con il prefisso di shipping contiene l'informazione relativa all'indirizzo di consegna, mentre l'elemento street con il prefisso billing contiene l'informazione relativa all'indirizzo di fatturazione.

Nodo istruzione di elaborazione (processing instruction node)

Le istruzioni di elaborazione nei documenti XML si trovano al di fuori della struttura ad albero dei documenti e sono indicate nella terminologia XPath come nodi istruzione di elaborazione. Un nodo istruzione di elaborazione inizia con <? e finisce con ?>.

Nell'esempio di codice mostrato sopra, troverete le seguenti istruzioni di elaborazione:

<?xml-stylesheet type="text/css" href="style.css"?>

La dichiarazione XML all'inizio del file XML è strutturata sintatticamente come un'istruzione di elaborazione, ma non è un nodo di istruzione di elaborazione come inteso dal modello di dati XPath.

Nodo commento (comment node)

I contenuti di un documento XML che sono stati contrassegnati come commenti vengono elaborati da XPath come nodi commento. Questo nodo contiene soltanto il contenuto dei caratteri contrassegnati, non la marcatura.

Nell'esempio di codice mostrato sopra troverete il seguente nodo commento:

That is a comment!

Percorsi di localizzazione

L'indirizzamento dei nodi viene effettuato utilizzando i cosiddetti percorsi di localizzazione. Un percorso di localizzazione è un'espressione XPath utilizzata per navigare attraverso la struttura ad albero e selezionare un determinato insieme di nodi. L'insieme di nodi è il risultato di un'espressione XPath.

I percorsi di localizzazione vengono valutati da sinistra a destra. Si distingue tra percorsi di localizzazione assoluti e relativi. Un percorso di localizzazione assoluto inizia dal nodo documento. In questo caso, l'espressione XPath inizia con una barra (/). I percorsi di localizzazione relativi invece partono da qualsiasi nodo all'interno della struttura ad albero. Questo punto di partenza è chiamato nodo contesto.

Un percorso di localizzazione consiste in singoli passi di localizzazione, che sono separati da barre (/) come nel caso dell'indirizzamento dei file nei sistemi di directory.

Ogni passo di localizzazione di un percorso è composto da un massimo di tre parti: asse, test di nodo e un qualsiasi numero di predicati.

  • Asse: scegliendo l'asse si determina la direzione di navigazione nella struttura ad albero a partire dal nodo contesto o dal nodo documento.
  • Test di nodo: il test di nodo corrisponde a un filtro che consente di selezionare un determinato set di nodi sull'asse.
  • I predicati: i predicati consentono di filtrare ulteriormente i nodi selezionati mediante l'asse e il test dei nodi.

I passi di localizzazione di un'espressione XPath vengono indicati con la sintassi seguente:

asse::nodo-test[predicato1][predicato2]…
Notazione Funzione
/ Separatore di percorso tra due passi di localizzazione
:: Separatore di percorso tra l'asse e il test di nodo

Assi

La sintassi XPath permette la navigazione utilizzando i seguenti assi.

Asse Designazione italiana Nodi selezionati child figlio Tutti i nodi figlio direttamente subordinati parent nodo genitore Il nodo genitore direttamente superiore descendant discendente Tutti i nodi subordinati ancestor* antenato Tutti i nodi di livello superiore following nodi successivi Tutti i nodi successivi nella sequenza del documento, ad eccezione dei discendenti preceding* nodi precedenti Tutti i nodi precedenti nella sequenza del documento, ad eccezione degli antenati following-sibling nodi fratelli successivi Tutti i nodi successivi nel documento XML che discendono dallo stesso nodo genitore preceding-sibling* nodi fratelli precedenti Tutti i nodi precedenti nel documento XML che provengono dallo stesso nodo genitore attribute attributo Tutti i nodi attributo di un nodo elemento namespace spazio di nomi Tutti i nodi namespace di un nodo elemento; a partire dalla versione 2.0, questo asse non è più incluso nella specifica. self nodo corrente Il nodo contesto stesso descendant-or-self discendenti compreso il nodo corrente Tutti i nodi subordinati, compreso il nodo contesto ancestor-or-self* antenati o nodi correnti Tutti i nodi di livello superiore, compreso il nodo contesto

N.B.

Gli assi contrassegnati con un asterisco (*) vanno in ordine rovesciato e sono considerati opzionali in base alle specifiche XPath versione 1.0, pertanto non devono essere necessariamente supportati da applicazioni conformi allo standard.

Il grafico seguente mostra una rappresentazione schematica degli assi più importanti del modello di dati XPath a partire dal nodo contesto (in rosso).

Ad esempio, l'asse child:: seleziona tutti gli elementi figlio del nodo contesto D: il set di nodi comprende i nodi E, H e I.

Test di nodo

Con il test di nodo potete definire un filtro per il set di nodi selezionato dall'asse. Secondo la specifica XPath, sono possibili due criteri di filtraggio.

  • Nome del nodo: immettere un nome di nodo come test di nodo per selezionare tutti i nodi con il nome corrispondente sull'asse selezionato.
  • Tipo di nodo: immettere un tipo di nodo come test di nodo per selezionare tutti i nodi del tipo corrispondente sull'asse selezionato.

Nome del nodo come criterio di filtraggio

Con il seguente percorso di localizzazione, ad esempio, è possibile, sulla base dell'esempio di codice mostrato sopra, selezionare tutti i discendenti con il nome book a partire dal nodo documento.

/descendant::book

Se invece volete filtrare l'attributo isbn da tutti i nodi elemento con il nome book dovete applicare due passi di localizzazione.

/descendant::book/attribute::isbn

Tipo di nodo come criterio di filtraggio

Se volete definire un tipo di nodo come criterio di filtraggio per la selezione del set di nodi, utilizzate come test di nodo una delle seguenti funzioni:

Funzione Nodi selezionati
node() La funzione node() seleziona tutti i nodi sull'asse selezionato.
text() La funzione text() seleziona tutti i nodi testo sull'asse selezionato.
comment() La funzione comment() seleziona tutti i nodi commento sull'asse selezionato.
processing-instruction() La funzione processing-instruction() seleziona tutti i nodi istruzione per l’elaborazione sull'asse selezionato.
N.B.

Già XPath 1.0 definisce 25 funzioni. A partire da XPath 2.0 sono disponibili 111 funzioni per descrivere i percorsi di localizzazione. Nella Raccomandazione W3C XPath and XQuery Functions and Operators 3.1 del 21 marzo 2017 troverete una panoramica delle funzioni.

Test di nodo con Wildcard

Se utilizzate il metacarattere* (asterisco) invece del test di nodo, vengono selezionati sull'asse tutti i nodi che corrispondono al principale tipo di nodo dell'asse. La regola è che se l'asse contiene nodi elemento, questo rappresenta il suo tipo di nodo principale. Questo vale per tutti gli assi ad eccezione di quelli attribute e namespace, per i quali si considera il tipo di nodo principale i nodi attributo o namespace.

Ad esempio, il seguente percorso di localizzazione mostra tutti gli attributi del nodo contesto corrente:

attribute::*

Sintassi abbreviata

Sono state definite abbreviazioni per gli assi e i passi di localizzazione di uso frequente, che possono essere utilizzate al posto dei nomi inglesi nell'espressione XPath.

Sintassi standard Abbreviazione Esempio
child:: vuoto Child rappresenta l'asse standard. Se necessario, questa notazione dell'asse può essere omessa. Il percorso di localizzazione child::book/child::title corrisponde quindi alla forma abbreviata book/title.
attribute:: @ L'asse attribute, separatore incluso, può essere abbreviato con il carattere @.
Il percorso di localizzazione book/attribute::isbn seleziona il nodo attributo isbn dell'elemento book e corrisponde alla sintassi abbreviata book/@isbn.
/descendant-or-self::node()/ // Il passo di localizzazione /descendant-or-self::node()/ seleziona il nodo documento e tutti i discendenti e viene abbreviato con //. Invece di /descendant-or-self::node()/child::item è possibile scrivere //item. Il percorso di localizzazione seleziona tutti i nodi item del documento.
parent::node() .. Il passo di localizzazione parent::node() seleziona il nodo genitore del nodo contesto ed è abbreviato con "..".
self::node() . Il passo di localizzazione self::node() seleziona il nodo contesto corrente e viene abbreviato con ".".

Predicati

I predicati vengono utilizzati per definire criteri di filtraggio aggiuntivi per il set di nodi selezionati attraverso l'asse e il test di nodo.

I predicati costituiscono la terza parte opzionale di un passo di localizzazione e vengono indicati tra parentesi quadre. I criteri di filtraggio all'interno delle parentesi quadre sono formulati come espressioni, che possono contenere espressioni di percorso, funzioni, operatori e stringhe.

La sintassi XPath supporta predicati generici e predicati numerici.

Predicati generici

Le espressioni dei predicati generici filtrano il set di nodi selezionato dall'asse e dal test di nodo producendo un valore booleano (true o false) per ogni nodo nella selezione. Tutti i nodi con il valore true fanno parte del set di risultati.

Le espressioni dei predicati generici vengono formulate utilizzando gli operatori, che vengono usati per selezionare in modo mirato i nodi con determinati contenuti o proprietà, per esempio tutti i nodi che contengono una stringa, un valore di attributo o un elemento figlio (possibilmente in un luogo determinato) specifici.

Le seguenti tabelle forniscono una panoramica degli operatori disponibili. Si distingue tra operatori aritmetici, operatori logici e operatori relazionali.

Operatori aritmetici Funzione
+ Addizione
- Sottrazione
* Moltiplicazione
div Divisione
mod Modulo
 
Operatori relazionali Funzione
= Uguale
!= Diverso
< Minore; mascheramento richiesto in XSLT (&lt;)
> Maggiore; mascheramento raccomandato in XSLT (&gt;)
<= Minore o uguale; mascheramento richiesto in XSLT (&lt;)
>= Maggiore o uguale; mascheramento raccomandato in XSLT (&gt;)
 
Operatori logici Funzione
and AND logico
or OR logico

Nel seguente esempio, il predicato [title="Harry Potter and the Prisoner of Azkaban"] limita il set di risultati a un nodo elementocon il nome book, il cuielemento figlio title contiene la stringa Harry Potter and the Prisoner of Azkaban.

N.B.

L'esempio corrisponde alla sintassi di XPath 3, che potrebbe non essere supportata da tutti gli strumenti online. Le interrogazioni qui presentate possono essere verificate, ad esempio, con il seguente tester online: http://videlibri.sourceforge.net/cgi-bin/xidelcgi.

/order/items/book[title="Harry Potter and the Prisoner of Azkaban"] 
Abbiamo ora selezionato il nodo elemento book, che contiene i dati per il libro di Harry Potter.
<book isbn="9781408845660">
            <title>Harry Potter and the Prisoner of Azkaban</title>
            <quantity>1</quantity>
            <priceus>22.94</priceus>
            <comment>Please confirm delivery date until Christmas.</comment>
        </book>

Un altro elementofiglio di questonodo elemento è l'elemento comment. Perselezionarne il contenuto è sufficiente aggiungere altri due passi al percorso di localizzazione.

/order/items/book[title="Harry Potter and the Prisoner of Azkaban"]/comment/text()

Con il passo di localizzazione comment (sintassi breve per child::comment)navighiamo all'omonimo elemento figlio dell'elemento book e selezioniamo il suo nodo testo con la funzione text(). Questo passaggio corrisponde alla seguente stringa:

Please confirm delivery date until Christmas.

Se in un predicato viene utilizzata solo l'espressione di un percorso si parla di test di esistenza. Per esempio, il seguente percorso di localizzazione potrebbe essere usato per verificare se il documento XML sopra riportato contiene uno o più nodi con il nome comment.

Sintassi abbreviata:

//book[comment]

Sintassi standard:

/descendant-or-self::node()/child::book[child::comment]

Il percorso di localizzazione //book[comment] seleziona tutti i nodi con il nome book che hanno un elemento figlio con il nome comment.

Predicati numerici

I predicati numerici consentono di indirizzare i nodi in base alla loro posizione. Il seguente percorso di localizzazione, ad esempio, seleziona, in base alla sequenza del documento, il secondo nodo con il nome book:

//book[2]

Il predicato [2] è in realtà l'abbreviazione della funzione [position()=2]. XPath seleziona quindi prima tutti i nodi con il nome "book" e filtra poi il nodo per il quale la funzione position()=2 restituisce il valore booleano true.

N.B.

A differenza di altri linguaggi di programmazione, le enumerazioni XPath iniziano con 1.

Ulteriori informazioni sul linguaggio XML Path Language

Una panoramica dell'attuale stato di sviluppo del linguaggio XML Path Language e di tutti gli standard e delle bozze pubblicate è consultabile sul sito web del W3C.

Informazioni e strumenti gratuiti per l'utilizzo di XPath nelle applicazioni web sono disponibili nei MDN Web Docs e nel Microsoft Developer Network.

Come fonte in lingua italiana raccomandiamo anche la guida di HTML.it.


Abbiamo una proposta per te:
Web hosting a partire da 1 €/mese!

Dominio gratis
Certificato SSL Wildcard incluso
Assistenza clienti 24/7
A partire da 1 €/mese IVA escl. per un anno,
poi 8 €/ mese IVA escl.