ago 28 2009

Interrogazioni XQuery in Java

Categoria: Programmazione Javasaverio @ 10:28

xqueryXQuery, una abbrevazione per XML Query Language, è un linguaggio di programmazione specificato dal W3C e destinato ad interrogare documenti e basi di dati XML. Questo perché XML si sta proponendo come la tecnologia per rimpiazzare i vecchi DBMS relazionali :-)

Il w3c ha definito il linguaggio XQuery 1.0; usa la sintassi delle espressioni di XPath  2.0, con l’aggiunta delle cosiddette espressioni FLWOR per la formulazione di query complesse. Il risultato è un linguaggio di programmazione funzionale, dichiarativo, con somiglianze con il vecchio SQL.

Per effettuare delle query xquery su un file XML possiamo usare delle librerie come BaseX e Saxon. Purtroppo attualmente Saxon non è un prodotto del tutto gratuito, quindi scegliamo di usare BaseX, un processore Xquery-XPath open source.

In realtà BaseX, oltre ad essere utlilizzabile come libreria all’interno del linguaggio Java, ci mette a disposizione un’interfaccia grafica dalla quale possiamo effettuare query su file XML ben formati arbitrari.

Primo esempio di query

La prima cosa da fare è inserire i file jar di BaseX nel build path del nostro progetto; la seconda è assicurarsi di avere java 1.6 (non funziona con java 1.5) perché BaseX utilizza il package javax.xml.stream.

Questo è un sempio dove si esegue la query //li sul file ‘input‘:

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import javax.xml.xquery.XQConnection;
import javax.xml.xquery.XQDataSource;
import javax.xml.xquery.XQPreparedExpression;
import javax.xml.xquery.XQResultSequence;
 
public final class XQueryAPIExample {
 /** Database Driver. */
 static final String DRIVER = "org.basex.api.xqj.BXQDataSource";
 
 public static void main(final String[] args) throws Exception {
 
 // Gets the XQDataSource for the specified Driver.
 XQDataSource source = (XQDataSource) Class.forName(DRIVER).newInstance();
 
 // Creates an XQConnection
 XQConnection conn = source.getConnection();
 
 // Prepares the Expressionwith the Document and the Query.
 XQPreparedExpression expr = conn.prepareExpression("doc('input')//li");
 
 // Executes the XQuery query.
 XQResultSequence result = expr.executeQuery();
 
 // Gets all results of the execution.
 while(result.next()) {
 // Prints the results to the console.
 System.out.println(result.getItemAsString(null));
 }
 
 }
}

Questo esempio funziona solo se il file XML interrogato non dichiara nessun namespace.

Query in presenza di namespace

Supponiamo adesso di interrogare un file XML con namespace… ad esempio un file in formato XML Mpeg-7 che usa i seguenti namespace:
xmlns=”urn:mpeg:mpeg7:schema:2001″
xmlns:mpeg7=”urn:mpeg:mpeg7:schema:2001″
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”

Per far riconoscere i namespace dobbiamo dichiararli nel prologo della xquery in questo modo:
declare default element namespace “urn:mpeg:mpeg7:schema:2001″
declare  namespace mpeg7 = “urn:mpeg:mpeg7:schema:2001″
declare  namespace xsi = “http://www.w3.org/2001/XMLSchema-instance”

Questo è il codice che esegue la query sul file file/video/extract.xml:

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
String prologoQuery = "" +
 "declare default element namespace \"urn:mpeg:mpeg7:schema:2001\"; " +
 "declare  namespace mpeg7 = \"urn:mpeg:mpeg7:schema:2001\"; " +
 "declare  namespace xsi = \"http://www.w3.org/2001/XMLSchema-instance\"; ";
 
 // Gets the XQDataSource for the specified Driver.
 XQDataSource source = (XQDataSource) Class.forName(DRIVER).newInstance();
 // Creates an XQConnection
 XQConnection conn = source.getConnection();
 // Prepares the Expressionwith the Document and the Query.
 //XQPreparedExpression expr = conn.prepareExpression("<xml>1 + 2 = { 1+2 }</xml>/text()");
 //XQPreparedExpression expr = conn.prepareExpression("doc('file/video/20090201_video_15213221.xml')//meta");
 XQPreparedExpression expr = conn.prepareExpression(prologoQuery + " doc('file/video/extract.xml')//Name");
 
 // Executes the XQuery query.
 XQResultSequence result = expr.executeQuery();
 // Gets all results of the execution.
 while(result.next()) {
 //element = (org.w3c.dom.Element) result.getObject();
 System.out.println(result.getItemAsString(null));
 }

Nella riga 18 è commentato un altro modo per usare gli oggetti restiuiti dalla query, che ci restituisce il risultato come elementi della struttura DOM del file XML.

Tags: , ,

8 Commenti a “Interrogazioni XQuery in Java”

  1. Marcy e Ceci says:

    X Saverio
    Cercando su internet info su Xquery ci siamo imbattute in un nome che ci ispirava fiducia….e siamo rimaste piacevolmente sorprese nel vedere che l’esempio era “casualmente” mooolto simile al nostro progetto :D

  2. Franco says:

    Ho un piccolo problema.
    i package non me li fa importare???perchè??
    grazie

  3. saverio says:

    Ciao Franco,
    i package me li fa importare senza problemi… sono solo un pò grandi :)

    Per questo non ti posso aiutare perchè si tratta di configurare correttamente il tuo IDE.

  4. Franco says:

    Grazie saverio ci sono riuscito…non avevo importato i package giusti….
    Una cosa che non ho capito è:
    static final String DRIVER = “org.basex.api.xqj.BXQDataSource”;
    a cosa serve??
    In jdbc il driver è relativo al database. Perchè qui uso una classe???
    Grazie mille

  5. saverio says:

    Ciao Franco,

    la stringa “org.basex.api.xqj.BXQDataSource” individua il driver da usare per eseguire le query.
    Come tu hai detto la cosa è analoga a JDBC: ci possono essere più motori di interrogazione xquery, ognuno associato con un driver.

    BaseX usa i file XML per creare un database semi-strutturato, e tutte le successive operazioni sono fatte su questo database. Stai attendo a non confonderti con i database relazionali!

  6. Franco says:

    Grazie mille….

  7. Franco says:

    Un’altra piccola cosa (scusa il disturbo).
    Ma baseX ha solo un driver?? Oppure ne posso utilizzare altri??
    Grazie mille ancora, mi stai dando una mano enorme!!!

  8. saverio says:

    Ciao Franco, scusa il ritardo :)

    Penso che BaseX abbia solamente un driver, però c’è la possibilità di usare sia le API standard Java, sia direttamente le sue API.

Scrivi un commento