XQuery

XQuery uses the structure of XML intelligently to express queries across the diverse kinds of data XML can be used to represent.


November 06, 2007
URL:http://www.drdobbs.com/database/xquery/202802962

Sam is a developer at Harmonia. He can be contacted at [email protected]. Paul is a lead developer at Harmonia. He can be contacted at [email protected].


Widespread use of XML has established it as a lingua franca. The choice of XML to represent ever-increasing amounts of data led to the need for a query language that uses the structure of XML intelligently to express queries across the diverse kinds of data XML can be used to represent. W3C has developed a formal specification of such a query language; it is called XQuery.

The best approach to learning XQuery is one that comes naturally to developers—examine a few examples and start writing queries. The eXist open-source native XML database (http://exist.sourceforge.net) comes with a sandbox that makes such an approach easy; see Figure 1. In the upper window, the query doc("musicians.xml")/musicians/musician searches the document contained in the file "musicians.xml" (Listing One) for all musician nodes that are children of the node named musicians. The results of the query are displayed in the lower window.

[Click image to view at full size]

Figure 1: eXist XML database sandbox.

<?xml version="1.0" encoding="UTF-8"?>
<musicians>
 <musician uid="1111">
  <nickname>Slash</nickname>
  <name>Saul Hudson</name>
     <instrument>Lead Guitar</instrument>
     <birthDate>1965-07-23</birthDate>
     <birthLocation>Hampstead, England</birthLocation>
 </musician>
 <musician uid="2222">
     <nickname>Axl Rose</nickname>
     <name>William Bruce Rose, Jr.</name>
     <instrument>Vocals</instrument>
     <birthDate>1962-02-06</birthDate>
     <birthLocation>Lafayette, Indiana, USA</birthLocation>
 </musician>
 <musician uid="3333">
     <nickname>Duff "Rose" McKagan</nickname>
     <name>Michael Andrew McKagan</name>
     <instrument>Bass Guitar</instrument>
     <birthDate>1964-02-05</birthDate>
     <birthLocation>Seattle, Washington, USA</birthLocation>
 </musician>
 <musician uid="4444">
     <name>Matt Sorum</name>
     <instrument>Drums</instrument>
     <birthDate>1960-11-19</birthDate>
     <birthLocation>Mission Viejo, California, USA</birthLocation>

 </musician>
 <musician uid="5555">
     <name>Izzy Stradlin</name>
     <instrument>Rhythm Guitar</instrument>
     <birthDate>1962-04-08</birthDate>
     <birthLocation>Lafayette, Indiana, USA</birthLocation>
 </musician>
 <musician uid="6666">
     <name>Scott Weiland</name>
     <instrument>Vocals</instrument>
     <birthDate>1967-10-27</birthDate>
     <birthLocation>Santa Cruz, California, USA</birthLocation>
 </musician>
 <musician uid="7777">
     <name>Dean DeLeo</name>
     <instrument>Lead Guitar</instrument>
     <birthDate>1961-08-23</birthDate>
     <birthLocation>Point Pleasant, New Jersey, USA</birthLocation>
 </musician>
 <musician uid="8888">
     <name>Robert Emile DeLeo</name>
     <instrument>Bass Guitar</instrument>
     <birthDate>1966-02-02</birthDate>
     <birthLocation>Montclair, New Jersey, USA</birthLocation>
 </musician>
</musicians>
Listing One

Using XQuery From Java

The eXist sandbox is an excellent learning tool and can be useful for composing and executing ad hoc queries; however, as you surely discovered when you used SQL, the real power of XQuery comes when it is used in an application. QueryExample.java (available online; see www.ddj.com/code/) is a Java program from the eXist Developer's Guide that can be used to execute XQueries. There are many implementations of XQuery. Because we had already installed eXist to use the sandbox, we chose the XML:DB API that eXist uses. This API can work with any native or XML-enabled database for which a suitable driver has been written. If you examine the Java code, you see that it is roughly analogous to using JDBC. You start by using the following code to load the driver:


String driver =    "org.exist.xmldb.DatabaseImpl";
Class cl = Class.forName(driver);	
  Database database =      (Database)cl.newInstance();
DatabaseManager.registerDatabase   (database);


The only difference between this code and its JDBC counterpart is the last line, which registers the Database object with the DatabaseManager. Each vendor delivers its own implementation of Database, which is the encapsulation of the database driver functionality that is necessary to access an XML database. The DatabaseManager class provides access to a Collection. The Collection interface represents a collection of Resources stored in an XML database. The Resource interface represents a container for data stored within the database.

Next, you get a Collection object using this code:


Collection col =    DatabaseManager.getCollection(
"xmldb:exist://localhost:8080   /exist/xmlrpc/db"


The URI starts with xmldb: and the rest is vendor specific, but the overall format resembles the URIs you have used in JDBC.

From the collection, you obtain a Service instance:


XPathQueryService service =
  (XPathQueryService) col.getService   ("XPathQueryService", "1.0");


XPathQueryService is an implementation of the Service interface that enables the execution of XPath queries within the context of a Collection or against a single XML Resource stored in the Collection. The Service interface is equivalent to the Statement interface in JDBC.

You then execute the query using the following statement:


ResourceSet result =    service.query(args[0]);


The argument to the query() method is a string whose contents is the XQuery. In our example, rather than hardcoding an XQuery, we generalized the program by accepting the XQuery as a command-line argument. The query() method returns a ResourceSet, which is similar to the ResultSet in JDBC. We complete our program by iterating over the ResourceSet and displaying the content of each Resource it contains. The code looks like this:


ResourceIterator i =    result.getIterator();
while(i.hasMoreResources()) {
  Resource r = i.nextResource();
    System.out.println       ((String)r.getContent());
    }


QueryResults (available online) shows the results obtained when you run the program using this command-line argument:


doc("musicians.xml")/musicians/musician[birthDate>="1960-01-01" and birthDate<"1965-01-01"] 

The Relation to XPath

If you are familiar with XPath, you'll recognize the syntax of the XQuery we just executed. That's because XQuery is built on XPath. XQuery 1.0 and XPath 2.0 share the same data model and support the same functions and operators. As a matter of fact, every XPath expression is a valid XQuery. This is good news because if you have already learned and used XPath, it won't take much additional study to master XQuery.

FLWOR

FLWOR, an acronym for "For, Let, Where, Order by, Return," describes a type of expression used in XQuery that is similar to the "SELECT FROM WHERE ORDER BY" you know from SQL. Here is a description of the FLWOR clauses:

Functions

The practice of placing frequently used segments of code into functions is common to all programming languages. XQuery is no different. We have already mentioned that XQuery supports the same functions as XPath. There are over 100 built-in functions (for a summary, see www.w3schools.com/xpath/xpath_functions .asp). You can also write your own functions. XQuery functions exist within a namespace. Each function name consists of a prefix that is a shortcut to the namespace followed by a colon followed by the function name. The default prefix, which you can see in the list of built-in functions, is fn:. For user-written functions, you can use the prefix local:.

A function that uses a FLWOR expression to perform the equivalent of the join with which you are familiar from SQL is printBandMemberInstrument (available online). It joins musicians.xml, which we have already seen, and band.xml (which is also available online). Notice that the return clause can contain XML tags as well as data.

Conclusion

XQuery provides the same power and flexibility for XML as SQL does for relational data. XQuery also makes it possible for you to query office documents—spreadsheets, word-processing documents, and the like. For more details, see Marc Van Cappellen's article "XQuery Your Office Documents" (www.ddj.com/linux-open-source/202401913).

Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.