XQuery API for Java
Developer(s) | Java Community Process |
---|---|
Stable release | 1.0 / June 24, 2009 |
Type | Data Access API |
Website | JSR 225: XQuery API for Java™ |
XQuery API for Java™ (XQJ) refers to the common Java API for the W3C XQuery 1.0 specification.
The XQJ API enables Java programmers to execute XQuery against an XML data source (e.g. an XML Database) while reducing or eliminating vendor lock in.
The XQJ API provides Java developers with an interface to the XQuery Data Model[1]. Its design is similar to the JDBC API which has a client/server feel and as such lends itself well to Server based XML Databases and less well to client-side XQuery processors, although the "connection" part is a very minor part of the entire API. Users of the XQJ API can bind Java values to XQuery expressions, preventing code injection attacks[2]. Also, multiple XQuery expressions can be executed as part of an atomic transaction.
Contents |
History and implementation
The XQuery API for Java™ was developed at the Java Community Process as JSR 225. It had some big technology backers such Oracle[3][4][5][6], IBM[5][6], BEA Systems[7], Software AG[8], Intel, Nokia and DataDirect[4].
Version 1.0 of the XQuery API for Java™ Specification was released on June 24, 2009[9], along with JavaDocs, a reference implementation and a TCK (Technology Compatibility Kit) which implementing vendors must conform to.
The XQJ classes are contained in the Java package javax.xml.xquery
Functionality
XQJ allows multiple implementations to exist and be used by the same application.
XQJ connections support creating and executing XQuery expressions. Expressions may be updating[10] and may include full text searches[11]. XQJ represents XQuery expressions using one of the following classes:
- XQExpression – the expression is sent to the XQuery processor every time.
- XQPreparedExpression – the expression is cached and the execution path is pre determined allowing it to be executed multiple times in an efficient manner.
XQuery expressions return a result sequence of XDM[1] items which in XQJ are represented through the XQResultSequence interface. The programmer can use an XQResultSequence to walk over individual XDM[1] items in the result sequence. Each item in the sequence has XDM[1] type information associated with it, such as its node type e.g. element(), document-node() or an XDM atomic type such as xs:string, xs:integer or xs:dateTime. XDM type information in XQJ can be retrieved via the XQItemType interface.
Atomic XQuery items can be easily cast to Java primitives via XQItemAccessor methods such as getByte() and getFloat(). Also XQuery items and sequences can be serialized to DOM Node
, SAX ContentHandler
, StAX XMLStreamReader
and the generic IO Reader
and InputStream
classes.
Examples
Basic Example
The following example illustrates creating a connection to an XML Database, submitting an XQuery expression, then processing the results in Java. Once all of the results have been processed, the connection is closed to free up all resources associated with it.
// create a new connection to an XML Database XQConnection conn = vendorDataSource.getConnection("myUser", "myPassword"); XQExpression expr = conn.createExpression(); // create a reusable XQuery Expression object XQResultSequence result = expr.executeQuery( "for $n in fn:collection('catalog')//item " + "return fn:data($n/name)"); // execute an XQuery expression // process the result sequence iteratively while (result.next()) { // Print the current item in the sequence System.out.println("Product name: " + result.getItemAsString(null)); } // free all resources created by the connection conn.close();
Binding a value to an external variable
The following example illustrates how a Java value can be bound to an external variable in an XQuery expression. Assume that the connection conn already exists
XQExpression expr = conn.createExpression(); // the XQuery expression to be executed String es = "declare variable $x as xs:integer external;" + " for $n in fn:collection('catalog')//item" + " where $n/price <= $x" + " return fn:data($n/name)"; // bind a value (21) to an external variable with the QName x expr.bindInt(new QName("x"), 21, null); // execute the XQuery expression XQResultSequence result = expr.executeQuery(es); // process the result (sequence) iteratively while (result.next()) { // process the result ... }
Default data type mapping
Mapping between Java and XQuery data types is largely flexible, however the XQJ 1.0 specification does have default mapping rules mapping data types when they are not specified by the user. These mapping rules are bare great similarities to the mapping rules found in JAXB.
The following table illustrates the default mapping rules for when binding Java values to external variables in XQuery expressions.
Java Datatype | Default XQuery Data Type(s) |
---|---|
boolean | xs:boolean |
byte | xs:byte |
byte[] | xs:hexBinary |
double | xs:double |
float | xs:float |
int | xs:int |
long | xs:long |
short | xs:short |
Boolean |
xs:boolean |
Byte |
xs:byte |
Float |
xs:float |
Double |
xs:double |
Integer |
xs:int |
Long |
xs:long |
Short |
xs:short |
String |
xs:string |
BigDecimal |
xs:decimal |
BigInteger |
xs:integer |
Duration |
xs:dayTimeDuration if the Duration Object's state is xs:dayTimeDuration |
xs:yearMonthDuration if the Duration Object's state is xs:yearMonthDuration | |
xs:duration if the Duration Object's state is xs:duration | |
XMLGregorianCalendar |
xs:date if the XMLGregorianCalendar Object's state is xs:date |
xs:dateTime if the XMLGregorianCalendar Object's state is xs:dateTime | |
xs:gDay if the XMLGregorianCalendar Object's state is xs:gDay | |
xs:gMonth if the XMLGregorianCalendar Object's state is xs:gMonth | |
xs:gMonthDay if the XMLGregorianCalendar Object's state is xs:gMonthDay | |
xs:gYear if the XMLGregorianCalendar Object's state is xs:gYear | |
xs:gYearMonth if the XMLGregorianCalendar Object's state is xs:gYearMonth | |
xs:time if the XMLGregorianCalendar Object's state is xs:time | |
QName |
xs:QName |
Document |
document-node(element(*, xs:untyped)) |
DocumentFragment |
document-node(element(*, xs:untyped)) |
Element |
element(*, xs:untyped) |
Attr |
attribute(*, xs:untypedAtomic) |
Comment |
comment() |
ProcessingInstruction |
processing-instruction() |
Text |
text() |
Known implementations
Native XML Databases
The following is a list of Native XML Databases which are known to have XQuery API for Java™ implementations.
Relational Databases
DataDirect provide XQJ adapters for relational databases, by translating XQuery code into SQL on the fly, then converting SQL result sets into a format suitable for XQJ to process further. The following is a couple of known implementations.
Client side implementations
The following is a list of client-side XQuery processors which provide an XQuery API for Java™ interface.
References
- ^ a b c d XQuery 1.0 and XPath 2.0 Data Model (XDM)
- ^ Binding Java Variables
- ^ Querying XML: XQuery, XPath, and SQL/XML in context - Jim Melton and Stephen Buxton. ISBN-13: 978-1558607118
- ^ a b XQJ - XQuery Java API is Completed, Marc Van Cappellen, Zhen Hua Liu, Jim Melton and Maxim Orgiyan
- ^ a b IBM and Oracle Submit XQuery API for Java (XQJ) Java Specification Request.
- ^ a b An Early Look at XQuery API for Java™ (XQJ) - Andrew Eisenberg, IBM and Jim Melton, Oracle
- ^ The BEA Streaming XQuery Processor
- ^ XQJ Interface for Tamino Native XML Database
- ^ JSR-000225 XQuery API for Java (Final Release)
- ^ XQuery Update Facility
- ^ XQuery Full Text
- ^ MarkLogic XQJ API
- ^ eXist XQJ API
- ^ BaseX XQJ API
- ^ Sedna XQJ API
- ^ Zorba 2.5 ships with a long awaited XQJ binding, 14th June 2012
- ^ Setting connection info using XQJ with Oracle 11g
- ^ Developing Scalable XML Applications with the Oracle XML Developer's Kit and XQuery API for Java Dmitry Lychagin, Oracle
- ^ How to XQuery Non-JDBC Sources from JDBC - Section XQJ
- ^ Running XQuery from Java applications using the XQJ API and the Oracle XDK implementation