XQuery in Java


There are a number of toolkits available to work with XQuery from within Java. This chapter uses the XMLBeans open source implementation from Apache for working with XQuery. XMLBeans is a technology for accessing XML by binding it to Java types. XMLBeans provides several ways to get at the XML, including the following:

  • q Through XML Schema, which has been compiled to generate Java types that represent schema types. In this way, you can access instances of the schema through JavaBeans-style accessors such as getXXX and setXXX.

  • q Reflect into the XML schema itself through an XML Schema Object model as provided by the XMLBeans API.

  • q With a cursor model through which you can traverse the full XML InfoSet.

  • q With XML DOM, which is completely supported.

Pre-requisites

Here are the prerequisites to working with XMLBeans:

  • q JDK 1.4 and Ant-Install these if you don't have them already.

  • q XMLBeans binaries-You can download them from http://www.xmlbeans.apache.org/sourceAndBinaries/index.html#XMLBeans+Binary+and+Development+Kit.

  • q Saxon XQuery processor for full XQuery support-For XMLBeans 2.2.0, you need Saxon 8.6.1, which you can download from http://www.prdownloads.sourceforge.net/saxon/saxonb8-6-1.zip?download.

  • q An editor for writing Java code-This could be a text editor or your favorite Java IDE.

With these items installed and configured, you are ready to work with XQuery from Java.

Selecting XML with XQuery

You can use XQuery to retrieve specific pieces of XML as you might retrieve data from a database. XQuery provides syntax for specifying the elements and attributes you're interested in. The XMLBeans API provides a method named execQuery() for executing XQuery expressions.

You can call them from and XmlObject instance (or a generated type inheriting from it) or an XmlCursor instance. First take a look at an example that invokes the execQuery() method from an XmlObject instance.

Invoking execQuery() from an XmlObject

Note that the XQuery expressions require additional classes on the class path, as noted in the XMLBeans installation instructions. You use the execQuery method to execute XQuery expressions. With XQuery expressions, the output XML returned is a copy of XML in the document queried against and this output is an array of type XmlObject.

The example in Listing 10-2 retrieves <Name> elements from the incoming XML, displaying them directly on the console.

Listing 10-2: Executing an XQuery expression from a Java application

image from book
      package com.wrox.xquery;      import org.apache.xmlbeans.XmlCursor;      import org.apache.xmlbeans.XmlObject;      public class XmlObjectSample      {        final static String m_namespaceDeclaration =          "declare namespace xq='http://www        public static void main(String[] args) throws Exception        {          String fileName = args[0];          XmlObject departmentDoc = XmlObject.Factory.parse(new URL(fileName));          //Get all the <Name> elements          String queryExpression =             "let $d := $this/xq:Departments " +             "return " +               "for $n in $d/xq:Department/ xq:Name " +               "return $n " ;          XmlObject[] results =            departmentDoc.execQuery(m_namespaceDeclaration + queryExpression);          //Print the results.          if (results.length > 0)          {            System.out.println("The query results: \n");            for (int i=0; i<results.length; i++)            {           System.out.println(results[i].toString() + "\n");            }          }          else          {            System.out.println("No results returned: \n");          }          }      } 
image from book

You start by creating an instance of XmlObject object passing in the XML filename as an argument:

      String fileName = args[0];      XmlObject departmentDoc = XmlObject.Factory.parse(new        URL(filename)); 

After that, you specify the query expression in a string variable:

            String queryExpression =        "let $d := $this/xq:Departments " +        "return " +            "for $n in $d/xq:Department/xq:Name " +              "return $n " ; 

This query expression first gets references to all the <Name> elements in the XML file and returns them as the output. The $this variable in the query expression refers to the current position.

You then actually execute the XQuery using the execQuery() method, passing in the value that is derived by combining the namespace declaration with the actual query expression:

      XmlObject[] results =        departmentDoc.execQuery(m_namespaceDeclaration + queryExpression); 

You then display the resultant output on the console through the System.out.println() method.

To test this Java program, create an XML file named Departments.xml with the contents shown in Listing 10-3.

Listing 10-3: Departments.xml file

image from book
      <?xml version="1.0" encoding="utf-8"?>      <Departments xmlns="http://www.wrox.com/xquery/samples/departments">        <Department>          <DepartmentID>1</DepartmentID>          <Name>Engineering</Name>          <GroupName>Research and Development</GroupName>        </Department>        <Department>          <DepartmentID>2</DepartmentID>          <Name>Tool Design</Name>          <GroupName>Research and Development</GroupName>        </Department>        <Department>          <DepartmentID>3</DepartmentID>          <Name>Sales</Name>          <GroupName>Sales and Marketing</GroupName>        </Department>        <Department>          <DepartmentID>4</DepartmentID>          <Name>Marketing</Name>          <GroupName>Sales and Marketing</GroupName>        </Department>        <Department>          <DepartmentID>5</DepartmentID>          <Name>Purchasing</Name>          <GroupName>Inventory Management</GroupName>        </Department>      </Departments> 
image from book

If you pass the URL of the Departments.xml file as a command-line argument at the time of executing the XmlObjectSample class, you will get the following output:

            <Name xmlns="http://www.wrox.com/xquery/samples/departments">Engineering</Name>      <Name xmlns="http://www.wrox.com/xquery/samples/departments">Tool Design</Name>      <Name xmlns="http://www.wrox.com/xquery/samples/departments">Sales</Name>      <Name xmlns="http://www.wrox.com/xquery/samples/departments">Marketing</Name>      <Name xmlns="http://www.wrox.com/xquery/samples/departments">Purchasing</Name> 

Invoking execQuery() from an XmlCursor

The XML cursor offers a fine-grained model for manipulating data in addition to providing you with a method to execute query expressions. The XML cursor API, analogous to the DOM's object API, is simply a way to point at a particular piece of data. So, just like a cursor helps navigate through a word processing document, the XML cursor defines a location in XML where you can perform actions on the selected XML.

Cursors are ideal for moving through an XML document when there's no schema available. After you've got the cursor at the location you're interested in, you can perform a variety of operations with it. For example, you can execute queries, set and get values, insert and remove fragments of XML, copy fragments of XML to other parts of the document, and make other fine-grained changes to the XML document. Listing 10-4 uses an XML cursor to execute an XQuery query.

Listing 10-4: Using XmlCursor to execute an XQuery expression

image from book
      package com.wrox.xquery;      import org.apache.xmlbeans.XmlCursor;      import org.apache.xmlbeans.XmlObject;      public class XmlCursorSample      {        final static String m_namespaceDeclaration =          "declare namespace xq='http://www        public static void main(String[] args) throws Exception        {          String fileName = args[0];          XmlObject departmentDoc = XmlObject.Factory.parse(new URL(fileName));          //Get the <Name> elements and return them          String queryExpression =            "let $d := $this/xq:Departments " +            "return " +              "for $n in $d/xq:Department/xq:Name " +              "return $n" ;          XmlCursor resultsCursor = departmentDoc.newCursor().execQuery            (m_namespaceDeclaration + queryExpression);          //Print the results          System.out.println(resultsCursor.xmlText());          }      } 
image from book

This code creates a new cursor at the start of the document. From there, it uses the XmlCursor interface's execQuery() method to execute the query expression:

      XmlCursor resultsCursor = departmentDoc.newCursor().execQuery        (m_namespaceDeclaration + queryExpression); 

After executing the query, the results are displayed through the call to the xmlText() method of the resultant XmlCursor:

      System.out.println(resultsCursor.xmlText()); 

Here is the output produced by the code.

      <xml-fragment>        <Name xmlns="http://www.wrox.com/xquery/samples/departments">Engineering</Name>        <Name xmlns="http://www.wrox.com/xquery/samples/departments">Tool Design</Name>        <Name xmlns="http://www.wrox.com/xquery/samples/departments">Sales</Name>        <Name xmlns="http://www.wrox.com/xquery/samples/departments">Marketing</Name>        <Name xmlns="http://www.wrox.com/xquery/samples/departments">Purchasing</Name>      </xml-fragment> 




Professional XML
Professional XML (Programmer to Programmer)
ISBN: 0471777773
EAN: 2147483647
Year: 2004
Pages: 215

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net