XQuery - Guida rapida

Cos'è XQuery

XQuery è un linguaggio funzionale utilizzato per recuperare le informazioni archiviate in formato XML. XQuery può essere utilizzato su documenti XML, database relazionali contenenti dati in formati XML o database XML. XQuery 3.0 è una raccomandazione del W3C dell'8 aprile 2014.

La definizione di XQuery data dalla sua documentazione ufficiale è la seguente:

XQuery è un linguaggio standardizzato per combinare documenti, database, pagine Web e quasi qualsiasi altra cosa. È molto ampiamente implementato. È potente e facile da imparare. XQuery sta sostituendo i linguaggi middleware proprietari e i linguaggi di sviluppo di applicazioni Web. XQuery sta sostituendo i programmi Java o C ++ complessi con poche righe di codice. XQuery è più semplice da utilizzare e più facile da mantenere rispetto a molte altre alternative.

Caratteristiche

  • Functional Language - XQuery è un linguaggio per recuperare / interrogare dati basati su XML.

  • Analogous to SQL - XQuery sta a XML come SQL sta ai database.

  • XPath based - XQuery utilizza espressioni XPath per navigare nei documenti XML.

  • Universally accepted - XQuery è supportato da tutti i principali database.

  • W3C Standard - XQuery è uno standard W3C.

Vantaggi di XQuery

  • Utilizzando XQuery, è possibile recuperare dati sia gerarchici che tabulari.

  • XQuery può essere utilizzato per interrogare strutture ad albero e grafiche.

  • XQuery può essere utilizzato direttamente per interrogare le pagine web.

  • XQuery può essere utilizzato direttamente per creare pagine web.

  • XQuery può essere utilizzato per trasformare documenti xml.

  • XQuery è ideale per database basati su XML e database basati su oggetti. I database degli oggetti sono molto più flessibili e potenti dei database puramente tabulari.

Questo capitolo elabora come impostare la libreria XQuery in un ambiente di sviluppo locale.

Stiamo utilizzando un processore XQuery autonomo open source Saxon Home Edition (Saxon-HE) che è ampiamente utilizzato. Questo processore supporta XSLT 2.0, XQuery 3.0 e XPath 3.0 ed è altamente ottimizzato per le prestazioni. Il processore Saxon XQuery può essere utilizzato senza avere alcun database XML. Useremo un semplice documento XML come nostro database nei nostri esempi.

Per utilizzare il processore Saxon XQuery, dovresti avere saxon9he.jar, saxon9-test.jar, saxon9-unpack, saxon9-xqj.jar nel classpath dell'applicazione. Questi file jar sono disponibili nel file di downloadSaxonHE9-6-0-1J.zipScarica SaxonHE9-6-0-1J.zip .

Esempio

Useremo il processore Saxon XQuery basato su Java per testare books.xqy, un file contenente l'espressione XQuery rispetto al nostro documento XML di esempio, ovvero books.xml.

In questo esempio, vedremo come scrivere ed elaborare una query per ottenere gli elementi del titolo dei libri il cui prezzo è maggiore di 30.

books.xml

<?xml version="1.0" encoding="UTF-8"?>
<books>
   
   <book category="JAVA">
      <title lang="en">Learn Java in 24 Hours</title>
      <author>Robert</author>
      <year>2005</year>
      <price>30.00</price>
   </book>
   
   <book category="DOTNET">
      <title lang="en">Learn .Net in 24 hours</title>
      <author>Peter</author>
      <year>2011</year>
      <price>40.50</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XQuery in 24 hours</title>
      <author>Robert</author>
      <author>Peter</author> 
      <year>2013</year>
      <price>50.00</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XPath in 24 hours</title>
      <author>Jay Ban</author>
      <year>2010</year>
      <price>16.50</price>
   </book>
   
</books>

books.xqy

for $x in doc("books.xml")/books/book where $x/price>30
return $x/title

XQueryTester.java

package com.tutorialspoint.xquery;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

import javax.xml.xquery.XQConnection;
import javax.xml.xquery.XQDataSource;
import javax.xml.xquery.XQException;
import javax.xml.xquery.XQPreparedExpression;
import javax.xml.xquery.XQResultSequence;

import com.saxonica.xqj.SaxonXQDataSource;

public class XQueryTester {
   public static void main(String[] args){
      try {
         execute();
      }
      
      catch (FileNotFoundException e) {
         e.printStackTrace();
      }
      
      catch (XQException e) {
         e.printStackTrace();
      }
   }

   private static void execute() throws FileNotFoundException, XQException{
      InputStream inputStream = new FileInputStream(new File("books.xqy"));
      XQDataSource ds = new SaxonXQDataSource();
      XQConnection conn = ds.getConnection();
      XQPreparedExpression exp = conn.prepareExpression(inputStream);
      XQResultSequence result = exp.executeQuery();
      
      while (result.next()) {
         System.out.println(result.getItemAsString(null));
      }
   }	
}

Passaggi per eseguire XQuery su XML

  • Step 1 - Copia XQueryTester.java in qualsiasi posizione, ad esempio, E: > java

  • Step 2 - Copia books.xml nella stessa posizione, E: > java

  • Step 3 - Copia books.xqy nella stessa posizione, E: > java

  • Step 4- Compila XQueryTester.java usando la console. Assicurati di avere JDK 1.5 o successivo installato sulla tua macchina e che i classpath siano configurati. Per i dettagli su come utilizzare JAVA, vedere il nostro Tutorial su JAVA

E:\java\javac XQueryTester.java
  • Step 5 - Esegui XQueryTester

E:\java\java XQueryTester

Produzione

Otterrai il seguente risultato:

<title lang="en">Learn .Net in 24 hours</title>
<title lang="en">Learn XQuery in 24 hours</title>

Comprendere l'esempio

  • books.xml rappresenta i dati di esempio.

  • books.xqy rappresenta l'espressione XQuery che deve essere eseguita su books.xml. Capiremo l'espressione in dettaglio nel prossimo capitolo.

  • XQueryTester, un programma esecutore XQuery basato su Java, legge books.xqy, lo passa al processore di espressioni XQuery ed esegue l'espressione. Quindi il risultato viene stampato.

Esempio

Di seguito è riportato un documento XML di esempio contenente i record di una libreria di vari libri.

books.xml

<?xml version="1.0" encoding="UTF-8"?>
<books>
   
   <book category="JAVA">
      <title lang="en">Learn Java in 24 Hours</title>
      <author>Robert</author>
      <year>2005</year>
      <price>30.00</price>
   </book>
   
   <book category="DOTNET">
      <title lang="en">Learn .Net in 24 hours</title>
      <author>Peter</author>
      <year>2011</year>
      <price>70.50</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XQuery in 24 hours</title>
      <author>Robert</author>
      <author>Peter</author> 
      <year>2013</year>
      <price>50.00</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XPath in 24 hours</title>
      <author>Jay Ban</author>
      <year>2010</year>
      <price>16.50</price>
   </book>
   
</books>

Di seguito è riportato un documento Xquery di esempio contenente l'espressione di query da eseguire sul documento XML precedente. Lo scopo è ottenere gli elementi del titolo di quei nodi XML in cui il prezzo è maggiore di 30.

books.xqy

for $x in doc("books.xml")/books/book
where $x/price>30 return $x/title

Risultato

<title lang="en">Learn .Net in 24 hours</title>
<title lang="en">Learn XQuery in 24 hours</title>

Verifica risultato

Per verificare il risultato, sostituire il contenuto di books.xqy (fornito nel capitolo Configurazione dell'ambiente ) con l'espressione XQuery sopra ed eseguire il programma java XQueryTester.

Espressioni XQuery

Cerchiamo di capire ogni parte dell'espressione XQuery sopra.

Uso delle funzioni

doc("books.xml")

doc () è una delle funzioni XQuery utilizzata per individuare l'origine XML. Qui abbiamo passato "books.xml". Considerando il percorso relativo, books.xml dovrebbe trovarsi nello stesso percorso in cui è presente books.xqy.

Uso di espressioni XPath

doc("books.xml")/books/book

XQuery utilizza pesantemente le espressioni XPath per individuare la parte richiesta di XML su cui eseguire la ricerca. Qui abbiamo scelto tutti i nodi del libro disponibili nel nodo libri.

Itera gli oggetti

for $x in doc("books.xml")/books/book

XQuery tratta i dati xml come oggetti. Nell'esempio precedente, $ x rappresenta il nodo selezionato, mentre il ciclo for itera sulla raccolta di nodi.

Applica la condizione

where $x/price>30

Poiché $ x rappresenta il nodo selezionato, "/" viene utilizzato per ottenere il valore dell'elemento richiesto; La clausola "where" viene utilizzata per porre una condizione sui risultati della ricerca.

Restituisci il risultato

return $x/title

Poiché $ x rappresenta il nodo selezionato, "/" viene utilizzato per ottenere il valore dell'elemento richiesto, prezzo, titolo; La clausola "return" viene utilizzata per restituire gli elementi dai risultati della ricerca.

FLWOR è un acronimo che sta per "For, Let, Where, Order by, Return". Il seguente elenco mostra ciò che rappresentano in un'espressione FLWOR:

  • F - Per: seleziona una raccolta di tutti i nodi.

  • L - Let - Inserisce il risultato in una variabile XQuery.

  • W - Dove: seleziona i nodi specificati dalla condizione.

  • O - Ordina per: ordina i nodi specificati secondo i criteri.

  • R - Return - Restituisce il risultato finale.

Esempio

Di seguito è riportato un documento XML di esempio che contiene informazioni su una raccolta di libri. Useremo un'espressione FLWOR per recuperare i titoli di quei libri con un prezzo maggiore di 30.

books.xml

<?xml version="1.0" encoding="UTF-8"?>
<books>
   
   <book category="JAVA">
      <title lang="en">Learn Java in 24 Hours</title>
      <author>Robert</author>
      <year>2005</year>
      <price>30.00</price>
   </book>
   
   <book category="DOTNET">
      <title lang="en">Learn .Net in 24 hours</title>
      <author>Peter</author>
      <year>2011</year>
      <price>70.50</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XQuery in 24 hours</title>
      <author>Robert</author>
      <author>Peter</author> 
      <year>2013</year>
      <price>50.00</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XPath in 24 hours</title>
      <author>Jay Ban</author>
      <year>2010</year>
      <price>16.50</price>
   </book>
   
</books>

Il seguente documento Xquery contiene l'espressione di query da eseguire sul documento XML precedente.

books.xqy

let $books := (doc("books.xml")/books/book) return <results> { for $x in $books where $x/price>30
   order by $x/price return $x/title
}
</results>

Risultato

<title lang="en">Learn XQuery in 24 hours</title>
<title lang="en">Learn .Net in 24 hours</title>

Verifica risultato

Per verificare il risultato, sostituire il contenuto di books.xqy (fornito nel capitolo Configurazione dell'ambiente ) con l'espressione XQuery sopra ed eseguire il programma java XQueryTester.

XQuery può anche essere facilmente utilizzato per trasformare un documento XML in una pagina HTML. Dai un'occhiata al seguente esempio per capire come lo fa XQuery.

Esempio

Useremo lo stesso file books.xml. Il seguente esempio utilizza XQuery estrae i dati da books.xml e crea una tabella HTML contenente i titoli di tutti i libri insieme ai rispettivi prezzi.

books.xml

<?xml version="1.0" encoding="UTF-8"?>
<books>
   
   <book category="JAVA">
      <title lang="en">Learn Java in 24 Hours</title>
      <author>Robert</author>
      <year>2005</year>
      <price>30.00</price>
   </book>
   
   <book category="DOTNET">
      <title lang="en">Learn .Net in 24 hours</title>
      <author>Peter</author>
      <year>2011</year>
      <price>70.50</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XQuery in 24 hours</title>
      <author>Robert</author>
      <author>Peter</author> 
      <year>2013</year>
      <price>50.00</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XPath in 24 hours</title>
      <author>Jay Ban</author>
      <year>2010</year>
      <price>16.50</price>
   </book>
   
</books>

Di seguito è riportata l'espressione Xquery che deve essere eseguita sul documento XML precedente.

books.xqy

let $books := (doc("books.xml")/books/book) return <table><tr><th>Title</th><th>Price</th></tr> { for $x in $books order by $x/price
   return <tr><td>{data($x/title)}</td><td>{data($x/price)}</td></tr>
}
</table>
</results>

Risultato

<table>
   <tr>
      <th>Title</th>
      <th>Price</th>
   </tr>
   <tr>
      <td>Learn XPath in 24 hours</td>
      <td>16.50</td>
   </tr>   
   <tr>
      <td>Learn Java in 24 Hours</td>
      <td>30.00</td>
   </tr>
   <tr>
      <td>Learn XQuery in 24 hours</td>
      <td>50.00</td>
   </tr>   
   <tr>
      <td>Learn .Net in 24 hours</td>
      <td>70.50</td>
   </tr>
</table>

Verifica risultato

Per verificare il risultato, sostituire il contenuto di books.xqy (fornito nel capitolo Configurazione dell'ambiente ) con l'espressione XQuery sopra ed eseguire il programma java XQueryTester.

Espressioni XQuery

Qui abbiamo usato le seguenti espressioni XQuery:

  • funzione data () per valutare il valore dell'elemento title e

  • {} operatore per dire al processore XQuery di considerare data () come una funzione. Se l'operatore {} non viene utilizzato, data () verrà trattato come testo normale.

XQuery è compatibile con XPath. Utilizza espressioni XPath per limitare i risultati della ricerca sulle raccolte XML. Per ulteriori dettagli su come utilizzare XPath, vedere il nostro tutorial su XPath .

Ricorda la seguente espressione XPath che abbiamo usato in precedenza per ottenere l'elenco dei libri.

doc("books.xml")/books/book

Esempi XPath

Useremo il file books.xml e vi applicheremo XQuery.

books.xml

<?xml version="1.0" encoding="UTF-8"?>
<books>
   
   <book category="JAVA">
      <title lang="en">Learn Java in 24 Hours</title>
      <author>Robert</author>
      <year>2005</year>
      <price>30.00</price>
   </book>
   
   <book category="DOTNET">
      <title lang="en">Learn .Net in 24 hours</title>
      <author>Peter</author>
      <year>2011</year>
      <price>40.50</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XQuery in 24 hours</title>
      <author>Robert</author>
      <author>Peter</author> 
      <year>2013</year>
      <price>50.00</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XPath in 24 hours</title>
      <author>Jay Ban</author>
      <year>2010</year>
      <price>16.50</price>
   </book>
   
</books>

Abbiamo fornito qui tre versioni di un'istruzione XQuery che soddisfano lo stesso obiettivo di visualizzare i titoli dei libri con un valore di prezzo maggiore di 30.

XQuery - Versione 1

(: read the entire xml document :)
let $books := doc("books.xml") for $x in $books/books/book where $x/price > 30
return $x/title

Produzione

<title lang="en">Learn .Net in 24 hours</title>
<title lang="en">Learn XQuery in 24 hours</title>

XQuery - Versione 2

(: read all books :)
let $books := doc("books.xml")/books/book

for $x in $books
where $x/price > 30 return $x/title

Produzione

<title lang="en">Learn .Net in 24 hours</title>
<title lang="en">Learn XQuery in 24 hours</title>

XQuery - Versione 3

(: read books with price > 30 :)
let $books := doc("books.xml")/books/book[price > 30] for $x in $books return $x/title

Produzione

<title lang="en">Learn .Net in 24 hours</title>
<title lang="en">Learn XQuery in 24 hours</title>

Verifica il risultato

Per verificare il risultato, sostituire il contenuto di books.xqy (fornito nel capitolo Configurazione dell'ambiente ) con l'espressione XQuery sopra ed eseguire il programma java XQueryTester.

Le sequenze rappresentano una raccolta ordinata di elementi in cui gli elementi possono essere di tipo simile o diverso.

Creazione di una sequenza

Le sequenze vengono create utilizzando parentesi con stringhe all'interno di virgolette o virgolette doppie e numeri in quanto tali. Gli elementi XML possono essere utilizzati anche come elementi di una sequenza.

XQuery Expression

let $items := ('orange', <apple/>, <fruit type="juicy"/>, <vehicle type="car">sentro</vehicle>, 1,2,3,'a','b',"abc") let $count := count($items) return <result> <count>{$count}</count>
   
   <items>
      {
	     for $item in $items
         return <item>{$item}</item>
      }
   </items>
   
</result>

Produzione

<result>
   <count>10</count>
   <items>
      <item>orange</item>
      <item>
         <apple/>
      </item>
      <item>
         <fruit type="juicy"/>
      </item>
      <item>
         <vehicle type="car">Sentro</vehicle>
      </item>
      <item>1</item>
      <item>2</item>
      <item>3</item>
      <item>a</item>
      <item>b</item>
      <item>abc</item>
   </items>
</result>

Visualizzazione degli elementi di una sequenza

Gli elementi di una sequenza possono essere iterati uno per uno, utilizzando l'indice o il valore. L'esempio sopra ha iterato gli elementi di una sequenza uno per uno. Vediamo gli altri due modi in azione.

Espressione XQuery (indice)

let $items := (1,2,3,4,5,6)
let $count := count($items)
return
   <result>
      <count>{$count}</count> <items> { for $item in $items[2] return <item>{$item}</item>
      }
      </items>
      
   </result>

Produzione

<result>
   <count>6</count>
   <items>
      <item>2</item>
   </items>
</result>

Espressione XQuery (valore)

let $items := (1,2,3,4,5,6) let $count := count($items) return <result> <count>{$count}</count>
      
      <items>
      {
         for $item in $items[. = (1,2,3)]
         return <item>{$item}</item>
      }
      </items>
      
   </result>

Produzione

<result>
   <count>6</count>
   <items>
      <item>1</item>
      <item>2</item>
      <item>3</item>
   </items>
</result>

La tabella seguente elenca le funzioni di sequenza comunemente utilizzate fornite da XQuery.

Suor n Nome e descrizione
1

count ($ seq as item () *)

Conta gli elementi in una sequenza.

2

sum ($ seq as item () *)

Restituisce la somma degli elementi in una sequenza.

3

avg ($ seq as item () *)

Restituisce la media degli elementi in una sequenza.

4

min ($ seq come elemento () *)

Restituisce l'articolo con valore minimo in una sequenza.

5

max ($ seq come elemento () *)

Restituisce l'elemento con valore massimo in una sequenza.

6

valori-distinti ($ seq come elemento () *)

Restituisce selezionare elementi distinti da una sequenza.

7

sottosequenza ($ seq as item () *, $startingLoc as xs:double, $lunghezza come xs: doppia)

Restituisce un sottoinsieme della sequenza fornita.

8

inserire prima ($seq as item()*, $posizione come xs: intero, $ inserisce come elemento () *)

Inserisce un elemento in una sequenza.

9

remove ($ seq as item () *, $ position as xs: integer)

Rimuove un elemento da una sequenza.

10

reverse ($ seq as item () *)

Restituisce la sequenza inversa.

11

indice di($seq as anyAtomicType()*, $target come anyAtomicType ())

Restituisce gli indici come numeri interi per indicare la disponibilità di un elemento all'interno di una sequenza.

12

scorso()

Restituisce l'ultimo elemento di una sequenza quando utilizzato nell'espressione del predicato.

13

posizione()

Utilizzato nelle espressioni FLOWR per ottenere la posizione di un elemento in una sequenza.

La tabella seguente elenca le funzioni di manipolazione delle stringhe comunemente usate fornite da XQuery.

Suor n Nome e descrizione
1

string-length ($ string as xs: string) as xs: integer

Restituisce la lunghezza della stringa.

2

concat ($ input as xs: anyAtomicType?) as xs: string

Restituisce la stringa concatenata come output.

3

string-join ($sequence as xs:string*, $delimitatore come xs: string) come xs: string

Restituisce la combinazione di elementi in una sequenza separata da un delimitatore.

La tabella seguente elenca le funzioni di data comunemente utilizzate fornite da XQuery.

Suor n Nome e descrizione
1

data odierna()

Restituisce la data corrente.

2

ora attuale()

Restituisce l'ora corrente.

3

current-dateTime ()

Restituisce sia la data corrente che l'ora corrente.

Di seguito è riportato l'elenco delle funzioni di espressioni regolari comunemente utilizzate fornite da XQuery

Suor n Nome e descrizione
1

partite ($input, $regex)

Restituisce vero se l'input corrisponde all'espressione regolare fornita.

2

sostituire($input, $regex, $ string)

Sostituisce la stringa di input corrispondente con la stringa data.

3

tokenize ($ input, $ regex)

Restituisce una sequenza di elementi che corrispondono all'espressione regolare.

XQuery fornisce un costrutto if-then-else molto utile per verificare la validità dei valori di input passati. Di seguito è riportata la sintassi del costrutto if-then-else.

Sintassi

if (condition) then
 ... 
else
 ...

Esempio

Useremo il seguente file books.xml e applicheremo ad esso un'espressione XQuery contenente un costrutto if-then-else per recuperare i titoli di quei libri con un valore di prezzo maggiore di 30.

books.xml

<?xml version="1.0" encoding="UTF-8"?>
<books>
   <book category="JAVA">
      <title lang="en">Learn Java in 24 Hours</title>
      <author>Robert</author>
      <year>2005</year>
      <price>30.00</price>
   </book>
   
   <book category="DOTNET">
      <title lang="en">Learn .Net in 24 hours</title>
      <author>Peter</author>
      <year>2011</year>
      <price>40.50</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XQuery in 24 hours</title>
      <author>Robert</author>
      <author>Peter</author>
      <year>2013</year>
      <price>50.00</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XPath in 24 hours</title>
      <author>Jay Ban</author>
      <year>2010</year>
      <price>16.50</price>
   </book>
</books>

La seguente espressione XQuery deve essere applicata al documento XML precedente.

books.xqy

<result>
{
   if(not(doc("books.xml"))) then (
      <error>
         <message>books.xml does not exist</message>
      </error>
   )
   else ( 
      for $x in doc("books.xml")/books/book	
      where $x/price>30 return $x/title
   )
}
</result>

Produzione

<result>
   <title lang="en">Learn .Net in 24 hours</title>
   <title lang="en">Learn XQuery in 24 hours</title>
</result>

Verifica il risultato

Per verificare il risultato, sostituire il contenuto di books.xqy (fornito nel capitolo Configurazione dell'ambiente ) con l'espressione XQuery sopra ed eseguire il programma java XQueryTester.

XQuery fornisce la capacità di scrivere funzioni personalizzate. Di seguito sono elencate le linee guida per creare una funzione personalizzata.

  • Usa la parola chiave declare function per definire una funzione.

  • Utilizza i tipi di dati definiti nello schema XML corrente

  • Racchiudere il corpo della funzione all'interno di parentesi graffe.

  • Prefisso il nome della funzione con uno spazio dei nomi XML.

La seguente sintassi viene utilizzata durante la creazione di una funzione personalizzata.

Sintassi

declare function prefix:function_name($parameter as datatype?...)
as returnDatatype?
{
   function body...
};

Esempio

Il seguente esempio mostra come creare una funzione definita dall'utente in XQuery.

XQuery Expression

declare function local:discount($price as xs:decimal?,$percentDiscount as xs:decimal?) as xs:decimal? { let $discount := $price - ($price * $percentDiscount div 100) return $discount
};

let $originalPrice := 100 let $discountAvailed := 10

return ( local:discount($originalPrice, $discountAvailed))

Produzione

90

Verifica il risultato

Per verificare il risultato, sostituire il contenuto di books.xqy (fornito nel capitolo Configurazione dell'ambiente ) con l'espressione XQuery sopra ed eseguire il programma java XQueryTester.