Learn XQuery |
Home:Learn XQuery:XQuery Tutorial:An XQJ Tutorial:Creating XDM Instances XQJ Tutorial Part IX: Creating XDM InstancesIn the previous chapters, we learned how to handle XDM instances that result from query execution; iterating through sequences; and getting access to the items in the sequence. What if we want to create an XDM instance, without executing a query? XQJ offers functionality to create both XQSequence and XQItem objects, not as a result of a query execution, but rather as standalone XDM instances. This functionality is offered through the XQDataFactory interface. An XQDataFactory can create the following types of objects:
Every XQConnection must implement the XQDataFactory interface. In XQJ 1.0 these are the only concrete XQDataFactory implementations; future XQJ versions might introduce different mechanisms to get access to an XQDataFactory. Creating TypesIn XQJ Tutorial Part VII: XQuery Type System, we introduced the XQItemType and XQSequenceType interfaces. We also showed how these objects are used to describe the static type of a query result and external variables. How do we create such type objects in our application? XQJ defines a dozen of XQITEMKIND_XXX constants. For each of them, there is a matching createXXXType method:
Let's take a closer look at some of the most commonly used methods. createAtomicTypeThe method createAtomicType(), creates an XQItemType object representing an XQuery atomic type. It accepts a single argument, an integer which is one of the predefined XQBASETYPE constants. The next example creates three XQItemType instances representing xs:integer, xs:string, and xs:decimal: ... Every XQConnection is an XQDataFactory; in the example we've used our XQConnection(xqc) to create these XQItemType instances. However, the XQItemType objects are completely independent of the connection. Where the above example shows how to create XQItemType objects representing one of the built-in atomic XML Schema types, there is a second flavor of createAtomicType() for user-defined atomic types. Assume a hatsize user-defined atomic type derived from xs:integer in the http://www.hatsize.com schema: ... createElementTypeBeside atomic types, element types are frequently used. In the next example we create an XQItemType representing element(person): ... The first argument to createElementType() is a QName. Where in the previous example a "person" element is created in no namespace, the next example creates an element type person in the namespace http://www.example.com. The second argument can be any of the predefined types; in addition to xs:anyType, xs:untyped is frequently used: ... The first argument can also be null, which is assumed to be the wild card. The following code snippet shows the creation of element(*, xs:untyped): ... createDocumentTypeWhat about document-node() types? In the following example we create two XQItemType instances, a first representing any document, and a second representing a well-formed untyped document: ... In addition to XQItemTypes, XQSequenceType objects can also be created. As explained in XQJ Tutorial Part VII: Typing, an XQSequence consists of:
As such creating an XQSequenceType is simple. The next example shows how to create a xs:string* sequence type: ... Using TypesSo, we now know how to create types. But why bother? How can we make use of all these types? Assume an XQSequence, iterating over the items. If the item is a node retrieve it through the DOM; get atomic values as Strings. This can be accomplished using the instanceOf() method, passing in an XQItemType object: ... Support for Static TypesSome XQuery implementations have support for the Static Typing Feature as defined in XQuery. This requires implementations to detect and report type errors during the static analyses phase. For expressions depending on the context item, the application must specify the static type of the context item. Why? In order to perform static typing, the implementation has to know the static type of the context item. The application has to provide the static type; failing to do so results in an error being reported during the static analysis phase. As the static type of the context item is a static context component, the XQJ XQStaticContext interface allows it to be manipulated. The next example shows how to set the static type of the initial context item to document-node(element(*, xs:untyped)): ... Overriding Default Type MappingsAs a last use case of XQItemType, think about some of the examples described in XQJ Tutorial Part VIII: Binding External Variables. The bindXXX() methods defined on XQDynamicContext have all a third parameter which allows you to override the default Java to XQuery data type mapping. In this example, we bind a Java Integer to the external variable; but rather than using the default mapping to xs:int, we specify to map it to a xs:short: ... How to Create XDM InstancesIn addition to its ability to create XQItemType and XQSequenceType instances, XQDataFactory also provides the ability to create XQItem and XQSequence instances. If this sounds familiar to you, it's because you understand the way binding to an XQDynamicContext works, as discussed in XQJ Tutorial Part VIII: Binding External Variables. Once you know this, you're more than half the way to understanding how XQItem instances are created. For every bindXXX() method defined on XQDynamicContext, there is a corresponding createItemFromXXX() method. Let's look at a simple example — binding a java.math.BigDecimal to an external variable $d: ... The following examples show how to create an XQItem of type xs:decimal from the same java.math.BigDecimal: ... XDM Instances and ConnectionsNote that the XQItem objects created through XQDataFactory are independent of any connection. Suppose you execute a query returning a single item, and subsequently close the connection but still require access to the XQItem. Closing the XQConnection will invalidate the XQItem object resulting from the query execution. Because of this, XQDataFactory has an XQItem copy method, createItem(). createItem() accepts a single XQItem argument, and returns a (deep) copy of the specified item. The following example shows how to make a query result available after closing the XQSequence or XQConnection: ... Reducing Parsing of Repeated QueriesImagine that you have an XML document that needs to be queried multiple times, but you don’t want to incur the XML parsing overhead each time it is queried. In the following example, two queries are executed, and books.xml is parsed twice: ... Or suppose you receive a transient XML stream, for example in a servlet environment, and need to query the stream multiple times. Then, one way or the other, the data will need to be buffered in order to query it more than once. How can we both ensure that an XML document is parsed only once, and, in the event the XML stream is transient, also make it 'queryable' multiple times? Consider two XQPreparedExpression objects, xqp1 and xqp2. The following example first creates an XQItem representing the XML document; as such it will be parsed only once. Next, it is bound to two different XQPreparedExpression objects: ... Such an approach, however, does have a couple of disadvantages, especially when working with a large documents — namely, scalability and memory consumption. For example, in the case of DataDirect XQuery, the streaming capabilities will not be of much use as the complete XML document is instantiated in-memory. As you might expect, however, there are techniques for handling large documents. See XQJ Tutorial Part XI: Processing Large Inputs for more information on this topic. Finally, XQDynamicContext also allows creating XQSequence objects. The createSequence() copy operation, with its XQSequence argument, lets you return a copy of an XQSequence object. As with the XQItem example above, it allows the possibility for query results to outlive an XQConnection. A second flavor of createSequence() accepts a java.util.Iterator, returning a sequence of items based on the objects returned by the Iterator. The objects are converted into XDM instances using the default object mapping defined in XQJ. For example, the following code snippet results in a sequence of xs:decimal instances: ...
|
New Case StudyGevity produces sales proposals in real time using DataDirect XQuery®. See how Gevity uses DataDirect XQuery® to combine Web service data from SalesForce.com with relational data in Oracle in a pricing engine for HR management. New Features in DataDirect XQuery®DataDirect XQuery® is now released! DataDirect XQuery® provides full update support for relational data, easy integration for Web Services, additional enhancements for performance and scalability and more! DataDirect XQuery FAQThis informative DataDirect XQuery® FAQ answers frequently-asked questions about DataDirect XQuery®, including questions about performance, scalability, use-cases, resources, and more. If you're more of a hands-on learner, then download a free copy and start exploring DataDirect XQuery® today! |





