XQJ Tutorial Part IV: Processing Query Results



XQJ Tutorial Part III: Querying Data from XML Files or Java XML APIs describes how to execute queries. In XQuery, query evaluation results in a sequence. In XQJ, executing a query through XQExpression or XQPreparedExpression returns an XQSequence object. An XQSequence represents an XQuery sequence and a cursor to iterate over the sequence.

Applications can navigate through an XQSequence using the next() method. Initially the current position of the XQSequence is before the first item. next() moves the current position forward and returns true if there is another item to be consumed. Once all items in the sequence have been read, next() returns false.

Let's iterate through a sequence:

...
XQExpression xqe;
XQSequence xqs;
xqe = xqc.createExpression();
xqs = xqe.executeQuery("doc('orders.xml')//order[id='174']");
while (xqs.next()) {
...
}
...

Retrieving Data Using Get Methods

Once positioned on an item, applications can retrieve the data using one of the getXXX() methods. Let’s take a look at some of these methods.

An application can use getObject() to retrieve the current item of an XQSequence as a Java object. XQJ defines a mapping for each of the XQuery item types to a Java object value.

Working with Elements

One of the most common scenarios is probably a query returning a sequence of elements. Using getObject(), XQJ defines a mapping to Java DOM elements:

...
org.w3c.dom.Element employee;
XQExpression xqe;
XQSequence xqs;
xqe = xqc.createExpression();
xqs = xqe.executeQuery("doc(employees.xml)//employee");
while (xqs.next()) {
employee = (org.w3c.dom.Element)xqs.getObject();
...
}
...

Working with Atomic Values

Actually, XQJ defines a mapping for every XQuery type to Java objects, including all the atomic types. Assume, for example, a query returning xs:decimal values; using getObject() your Java application retrieves the items as java.math.BigDecimal objects:

...
java.math.BigDecimal price;
XQExpression xqe;
XQSequence xqs;
xqe = xqc.createExpression();
xqs = xqe.executeQuery(
"doc('orders.xml')/orders/order/xs:decimal(total_price)");
while (xqs.next()) {
price = (java.math.BigDecimal)xqs.getObject();
...
}
...

Suppose you have a query returning atomic values, and you want to retrieve a textual (character string) representation to output to System.out. The getAtomicValue() method returns a character string representation of an atomic value according to the XQuery xs:string casting rules, and throws an exception if the item is not an atomic value (that is, if it’s a node).

In the next example the query returns a sequence of atomic values. Note that the items are not all of the same type:

...
XQExpression xqe = xqc.createExpression();
XQSequence xqs = xqe.executeQuery(
"'Hello world!', 123, 1E1, xs:QName('abc')");
while (xqs.next()) {
System.out.println(xqs.getAtomicValue());
}
...

Working with SAX and StAX

Beside the DOM, XQJ also provides native support for two other popular XML APIs — SAX and StAX. In the next example, each of the items is returned to the application through SAX:

...
ContentHandler ch = ...
XQExpression xqe = xqc.createExpression();
XQSequence xqs = xqe.executeQuery(
"doc(employees.xml)//employee");
while (xqs.next()) {
xqs.writeItemToSAX(ch);
}
...

Reading a Sequence as a Stream

So far we have seen a number of examples in which the application iterates over all the items in the sequence, and retrieves them one-by-one. The XQSequence interface also offers functionality to retrieve the complete sequence within a single call. The next example executes a query and serializes the complete result into a SAX event stream.

...
ContentHandler ch = ...
XQExpression xqe;
XQSequence xqs;
xqe = xqc.createExpression();
xqs = xqe.executeQuery("doc('employees.xml')//employee");
xqs.writeSequenceToSAX(ch);
...

Similarly, the following example reads the complete sequence as a StAX event stream:

...
XQExpression xqe = xqc.createExpression();
XQSequence xqs = xqe.executeQuery("doc('employees.xml')");
XMLStreamReader xmlReader = xqs.getSequenceAsStream();
while (xmlReader.next() != XMLStreamConstants.END_DOCUMENT) {
...
}
...

Besides exposing the sequence through a SAX or StAX event stream, XQSequence also provides the ability to serialize into a binary or character stream. Here we're entering the arena of XQJ Tutorial Part V: Serializing Query Requests.

Scrollable Sequences

The above examples all iterate forward through the XQSequence objects. XQJ has also the notion of scrollable sequences, allowing you to move both forward and backward through a sequence, set the cursor to an absolute position, and iterate through the XQSequence more than once.