Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

XQuery: interroghiamo XML

Il linguaggio di interrogazione XML Query, meglio noto nella sua abbreviazione XQuery è stato creato dal W3C per estrarre informazioni da documenti XML. È ancora in fase di sviluppo ma possiamo coglierne le potenzialità
Il linguaggio di interrogazione XML Query, meglio noto nella sua abbreviazione XQuery è stato creato dal W3C per estrarre informazioni da documenti XML. È ancora in fase di sviluppo ma possiamo coglierne le potenzialità
Link copiato negli appunti

Tra i principali vantaggi di XML c'è la possibilità di rappresentare dati di qualsiasi tipo. Con XML rappresentiamo (e quindi memorizziamo) documenti, pagine Web, immagini vettoriali, ma anche clienti, ordini, fatture, etc. Di conseguenza sorge la necessità di estrarre sottoinsiemi di dati dalla loro rappresentazione in XML. In altre parole di un linguaggio di interrogazione.

A questo scopo il W3C ha elaborato il linguaggio di interrogazione XML Query, meglio noto nella sua abbreviazione XQuery, tuttora in fase di definizione, che offrirà un approccio standard all'interrogazione di dati in forma rappresentati (o rappresentabili) mediante XML.

XQuery e la famiglia XML

Come avremo modo di vedere, XQuery ha alcune affinità con altre tecnologie della famiglia XML. In particolare questo linguaggio utilizza molto della sintassi di XPath. Entrambi condividono lo stesso modello di dati, cioè lavorano sulla struttura logica ad albero dei documenti XML.

Possiamo affermare che XQuery 1.0 è un'estensione di XPath 2.0 e che ogni espressione di XPath è anche un'espressione XQuery. Tra l'altro, come accade anche per XPath, in XQuery tutto è espressione, cioè qualsiasi combinazione sintattica valida viene valutata e restituisce un valore.

Rispetto a XPath, però, XQuery mette a disposizione nuove caratteristiche che gli consentono di restituire risultati in modo sofisticato, facendolo somigliare per certi versi a XSLT (almeno dal punto di vista delle funzionalità offerte). Ma andiamo per ordine e cominciamo ad esplorare XQuery partendo dalle cose più semplici.

Estrazione di nodi

Abbiamo detto che XQuery condivide lo stesso modello di dati e la stessa sintassi di XPath. Pertanto, se conoscete già XPath non avrete difficoltà a manipolare nodi ed elementi ed a navigare nell'albero di rappresentazione di un documento XML, districandovi tra antenati (ancestor) e discendenti (descendant), fratelli (sibling) e genitori (parent).

Per rinfrescare la memoria, facciamo un semplice esempio. Dato il seguente documento XML:

Listato 1. Rappresentazione ad albero di un documento xml

<?xml version="1.0" ?>
<magazzino codice="MAG1">

   <articolo codice="A1">
       <descrizione>Righello 25 cm</descrizione>
       <quantita>50</quantita>
   </articolo>

   <articolo codice="A2">
       <descrizione>Calcolatrice</descrizione>
       <quantita>60</quantita>
   </articolo>

   <articolo codice="A3">
       <descrizione>Quaderno a quadri</descrizione>
       <quantita>120</quantita>
   </articolo>
</magazzino>

l'espressione che segue

/magazzino/articolo[quantita > 100]

individua tutti gli elementi <articolo> il cui sottoelemento <quantita> ha un valore maggiore di 100. In particolare, nel nostro caso l'espressione individua l'elemento <articolo> con codice A3:

Risultato dell'interrogazione

<articolo codice="A3">
 <descrizione>Quaderno a quadri</descrizione>
 <quantita>120</quantita>
</articolo>

Per quanto detto prima, l'espressione XPath appena vista è anche una espressione XQuery. Supponendo che il documento XML in questione sia memorizzato in un file magazzino.xml, possiamo completare l'espressione nel seguente modo:

document("magazzino.xml")/magazzino/articolo[quantita > 100]

La funzione document() individua la fonte dei dati rappresentati tramite XML.

Espressioni FLWOR

Le differenze con XPath sono evidenziate dall'introduzione di costrutti che offrono una grande potenza e flessibilità e permettono di costruire le cosiddette espressioni FLWOR, si pronuncia come "flower", ed è un acronimo che deriva dai costrutti:

  • For che fornisce un meccanismo iterativo
  • Let che definisce un meccanismo per l'assegnamento
  • Where che consente di filtrare i risultati tramite condizioni booleane
  • Order by che offre un meccanismo di ordinamento
  • Return che indica l'espressione da valutare e restituire

Mostriamo con un semplice esempio come utilizzare questi costrutti. Facendo riferimento al documento XML mostrato all'inizio dell'articolo, supponiamo di voler estrarre le descrizioni di tutti gli articoli del magazzino in quantità inferiore a 100 ordinate alfabeticamente. Possiamo ottenere questo risultato con la seguente espressione XQuery:

Listato 2. Interrogazione con costrutti FLWOR

for $x in document("magazzino.xml")/magazzino/articolo
where $x/quantita < 100
let $y := $x/descrizione
order by $y
return $y

Questa espressione è costituita da un ciclo for che fa uso di una variabile $x per rappresentare ad ogni ciclo un elemento <articolo> del nostro documento XML. Tramite la clausola where specifichiamo il criterio di selezione degli elementi a cui siamo interessati. Assegniamo poi tramite let la descrizione dell'articolo alla variabile $y. Utilizziamo order by per indicare l'ordinamento ed infine con return indichiamo cosa restituire. Il risultato della valutazione di questa espressione sarà il seguente:

Risultato dell'interrogazione

<descrizione>Calcolatrice</descrizione>
<descrizione>Righello 25 cm</descrizione>

Naturalmente potremo avere espressioni più o meno complesse in base al risultato che vogliamo ottenere.

Risultati in HTML

Una caratteristica molto interessante delle espressioni XQuery consiste nella possibilità di essere inglobate all'interno di altri documenti, anche in forma annidata. In tal caso le espressioni devono essere racchiuse tra parentesi graffe. È possibile quindi sfruttare XQuery non solo come linguaggio di interrogazione, ma anche per la generazione dinamica di pagine HTML.

Vediamo un esempio facendo sempre riferimento al solito nostro documento XML. Supponiamo di voler generare una pagina HTML che elenca le descrizioni degli articoli estratti dalla precedente espressione FLWOR. Possiamo farlo con la seguente espressione XQuery:

Listato 5. Generazione di una pagina HTML

<html>
<head>
   <title>Articoli<title>
</head>
<body>
   <h1>Articoli con disponibilità inferiore a 100 unità</h1>
   <ul>
   {
   for $x in document("magazzino.xml")/magazzino/articolo
   where $x/quantita < 100
   order by $x/descrizione
   return <li>{data($x/descrizione)}</li>
   }
   </ul>
</body>
</html>

L'espressione è costituita da un template HTML contenente l'espressione FLWOR all'interno delle parentesi graffe. La clausola return genera un elemento <li> contenente il valore dell'elemento <descrizione> estratto tramite la funzione predefinita data(). Da notare come la chiamata data() viene racchiusa tra parantesi graffe dal momento che si trova all'interno di tag HTML. Il risultato della valutazione di questa espressione è la pagina HTML seguente:

Risultato dell'espressione

<html>
<head>
   <title>Articoli<title>
</head>
<body>
   <h1>Articoli con disponibilità inferiore a 100 unità</h1>
   <ul>
      <li>Calcolatrice</li>
      <li>Righello 25 cm</li>
   </ul>
</body>
</html>

Non è difficile immaginare le possibili applicazioni di questa caratteristica di XQuery. Le tecnologie di elaborazione server-side come ASP, PHP, JSP, ecc. hanno un nuovo potenziale concorrente!

Abbiamo visto come questo linguaggio estenda XPath offrendo costrutti per l'estrazione avanzata di dati rappresentati con XML fino ad offrire funzionalità di generazione dinamica di pagine HTML.

Nella parte precedente dell'articolo abbiamo introdotto le caratteristiche fondamentali di XQuery ed abbiamo avuto modo di osservarne le potenzialità. Anche se questo linguaggio si presenta come una tecnologia per l'interrogazione di dati rappresentati in XML, abbiamo visto come si presti bene anche per la generazione dinamica di pagine HTML (e potenzialmente anche di altri tipi di documenti). In questa seconda parte vedremo come XQuery presenta anche funzionalità abbastanza vicine ai linguaggi di programmazione.

Espressioni condizionali

Una di queste funzionalità è il costrutto if-then-else per la costruzione di espressioni condizionali. A differenza della maggior parte dei linguaggi di programmazione, la clausola else è obbligatoria in XQuery. Questo perchè tutto in XQuery è un'espressione e pertanto qualsiasi costrutto deve restituire un valore.

Per vedere all'opera il costrutto if-then-else, facciamo riferimento al documento XML mostrato nelle pagine precedenti, che per comodità riportiamo:

Listato 1. Documento XML che rappresenta un magazzino

<?xml version="1.0" ?>
<magazzino codice="MAG1">
  <articolo codice="A1">
    <descrizione>Righello 25 cm</descrizione>
    <quantita>50</quantita>
  </articolo>
  <articolo codice="A2">
    <descrizione>Calcolatrice</descrizione>
    <quantita>60</quantita>
  </articolo>
  <articolo codice="A3">
    <descrizione>Quaderno a quadri</descrizione>
    <quantita>120</quantita>
  </articolo>
</magazzino>

La seguente espressione XQuery:

Listato 2. Interrogazione condizionale con soglie di approvvigionamento

for $x in document("magazzino.xml")/magazzino/articolo
order by $x/descrizione
return if ($x/quantita <= 50) then
          <msg>{data($x/descrizione)} - quantità insufficiente</msg>
       else
          <msg>{data($x/descrizione)} - quantità sufficiente</msg>

restituisce una sequenza di elementi <msg> con la descrizione di ciascun articolo e la scritta "quantita sufficiente" se la quantità è superiore a 50, "quantità insufficiente" in caso contrario:

Risultato dell'interrogazione

<msg>Calcolatrice - quantità sufficiente</msg>
<msg>Quaderno a quadri - quantità sufficiente</msg>
<msg>Righello 25 cm - quantità insufficiente</msg>

Abbiamo detto che il costrutto if-then-else deve sempre prevedere la clausola else. Nel caso in cui non abbiamo da restituire un valore specifico per "else", o meglio, il valore restituito è nullo, possiamo specificarlo tramite l'espressione (), come nel seguente esempio:

Listato 3. Espressione condizionale con alternativa nulla

if ($x/quantita <= 50) then
  <msg>{data($x/descrizione)} - quantità insufficiente</msg>
else
  ()

Funzioni predefinite

Abbiamo già avuto modo di vedere alcune funzioni predefinite. In particolare abbiamo visto le funzioni document(), che restituisce la struttura di nodi di un documento XML, e data(), che restituisce il valore di un nodo.

XQuery prevede un vasto insieme di funzioni predefinite, condivise con XPath, che consentono di effettuare le operazioni più disparate: dal conteggio di elementi (count()) alla somma di valori (sum()), dalla concatenazione di stringhe (concat()) alla trasformazione in maiuscole (upper-case()), dall'estrazione di sottostringhe (substring()) all'individuazione della posizione di un nodo(position()).

Le funzioni predefinite appartengono al namespace identificato dall'URI http://www.w3.org/2005/02/xpath-functions al quale è associato il prefisso predefinito fn. Questo è il motivo per cui talvolta le funzioni vengono indicate con questo prefisso, ad esempio fn:max(). Tuttavia, dal momento che fn è il prefisso predefinito del namespace non è necessario indicarlo nelle chiamate di funzione.

Funzioni personalizzate

Se le funzioni predefinite non dovessero essere sufficienti per le nostre esigenze di elaborazione, XQuery prevede la possibilità di creare nuove funzioni, proprio come un linguaggio di programmazione strutturata. Se ad esempio abbiamo bisogno di una funzione per il calcolo dell'IVA di un articolo, possiamo definirla nel seguente modo:

Listato 4. Dichiarazione di una funzione per il calcolo dell'IVA

declare function local:ImportoIVA($prezzo as xs:decimal, $aliquota as xs:integer) as xs:decimal
{
  return ($prezzo * $aliquota div 100)
};

La dichiarazione di una nostra funzione prevede l'indicazione di un prefisso (local nell'esempio) in modo che le funzioni personalizzate possano essere distinte da quelle predefinite. È necessario indicare il tipo di dato dei parametri ed il tipo di dato restituito dalla funzione. A tale proposito, i tipi di dato previsti sono quelli degli XML Schema.

A questo punto possiamo invocare la nostra funzione in qualsiasi punto ne abbiamo necessità, come mostra l'esempio seguente:

Listato 5. Invocazione della funzione per l'IVA

return <iva>{local:ImportoIVA(data(x$/prezzo), data(x$/aliquota))}</iva>

La possibilità di definire le proprie funzioni apre la strada ad un vero e proprio linguaggio di programmazione che, unito alle capacità di interrogazione e di generazione di codice HTML, genera un vero e proprio framework per la generazione dinamica di pagine Web.

XQuery all'opera

Allo stato attuale XQuery non è ancora uno standard approvato dal W3C, ma si trova nello stato di Candidate Recommendation. Ciò vuol dire che le specifiche sono ancora soggette a revisione. Tuttavia, come abbiamo avuto modo di vedere, sono abbastanza delineate le potenzialità di questo linguaggio, tanto che numerose sono le implementazioni per poter cominciare ad utilizzarlo in pratica. Segnaliamo a questo proposito:

XQuery, pensato originariamente come linguaggio di interrogazione di documenti XML, ha le potenzialità per diventare un linguaggio di interrogazione universale. Esso può infatti essere utilizzato per l'interrogazione di database relazionali o di una qualsiasi fonte di dati rappresentabile secondo il modello XML.

Esistono già alcune implementazioni che consentono di sfruttare questa importante caratteristica. Citiamo tra le altre:

Possiamo annoverare anche database relazionali molto noti ed affermati, come

La presenza di un buon numero di implementazioni e del supporto di XQuery da parte di grossi produttori di software è indice dell'interesse che ruota intorno a questa tecnologia.

Conclusioni

Questo articolo chiude la sintetica panoramica su XQuery visto nei suoi elementi sintattici e semantici di base. Abbiamo visto come, pur partendo da un obiettivo ristretto come quello dell'interrogazione di documenti XML, questo linguaggio ha in realtà potenzialità più vaste. La ricchezza di implementazioni ed il supporto da parte di produttori di database molto diffusi fa pensare che prima o poi chi ha a che fare con gli aspetti tecnici dell'informatica dovrà imbattersi in questo linguaggio.

Bibliografia

Ti consigliamo anche