Executing a simple XQuery

Executing XQuery in Java

In the XQJ API, there are 2 classes to execute XQueries against an XML Datasource, XQExpression and XQPreparedExpression. For the moment we will focus on executing an XQuery via XQExpression

Let's execute an XQuery which finds the title's of all of the books within the 'books.xml' document.

Save the following source file in the 'src' directory as SimpleQuery.java. Compile and execute it making sure that sxqj-beta1.jar is on the classpath.

SimpleQuery.java

import javax.xml.xquery.*; import net.cfoster.sedna.xqj.SednaXQDataSource; public class SimpleQuery { public static void main(String[] args) throws XQException { XQDataSource xqs = new SednaXQDataSource(); xqs.setProperty("serverName", "localhost"); xqs.setProperty("databaseName", "test"); XQConnection conn = xqs.getConnection("SYSTEM", "MANAGER"); XQExpression xqe = conn.createExpression(); String xqueryString = "for $x in doc('books.xml')//book return $x/title/text()"; XQResultSequence rs = xqe.executeQuery(xqueryString); while(rs.next()) System.out.println(rs.getItemAsString(null)); conn.close(); } }

Should give the following output

XSLT 2.0 and XPath 2.0 (4th Edition)
XQuery
Java Web Services: Up and Running
Effective Java (2nd Edition)
Status Anxiety
Processing XML with Java: a Guide to SAX, DOM, JDOM, JAXP, and TrAX
Thai-English and English-Thai Dictionary
Psychological Types
XSL-FO: Making XML Look Good in Print
Data Structures in Java

Pretty neat, but so far we are just collecting text values and printing them. The XQJ API can actually deal with all XML Schema atomic types, e.g. xs:integer and xs:date.

Let's perform another query which collects all of the prices of the books which are essentially float values.

GetBookPrices.java

import javax.xml.xquery.*; import net.cfoster.sedna.xqj.SednaXQDataSource; public class GetBookPrices { public static void main(String[] args) throws XQException { XQDataSource xqs = new SednaXQDataSource(); xqs.setProperty("serverName", "localhost"); xqs.setProperty("databaseName", "test"); XQConnection conn = xqs.getConnection("SYSTEM", "MANAGER"); XQExpression xqe = conn.createExpression(); String xqueryString = "for $x in doc('books.xml')//book return xs:float($x/price)"; XQResultSequence rs = xqe.executeQuery(xqueryString); while(rs.next()) { float price = rs.getFloat(); System.out.println("price = " + price); } conn.close(); } }

Should produce the output

price = 33.99
price = 38.5
price = 26.99
price = 35.99
price = 9.99
price = 37.99
price = 14.95
price = 19.99
price = 26.99
price = 53.99

You'll notice here that you can extract data from your XQuery result sequences as a Java primitive type, you can also cast to Java Objects such as Float, Element / Document / Attr etc for W3C DOM values or XMLGregorianCalendar for date information for instance.

Because in the XQuery code we cast each '$x/price' value to the XML Schema datatype 'float', the server sends each result item with datatype information of xs:float to the XQJ client. This means the Java program can deal with the returned data in a native fashion without needing to convert text values to Java primitives or Objects manually.

NOTE: If '$x/price' was not cast to xs:float, a derivitive of xs:float or a number that could be cast to xs:float, the program would throw an XQException on calling the method 'rs.getFloat()'

XQuery 1.0 makes use of XML Schema datatypes for it's typing system (just as XPath 2.0 and XSLT 2.0 do).

Here are a couple of direct mappings between Java and XQuery datatypes within the XQJ.

Java DatatypeXQuery Datatype
booleanxs:boolean
bytexs:byte
doublexs:double
floatxs:float
intxs:int
longxs:long
shortxs:short
Document