How to Search XML Using XQuery from Java

Use XQuery for more powerful XML search than is possible with XPath

“I guess there are never enough books.” ― John Steinbeck, A John Steinbeck Encyclopedia

1. Introduction

XPath offers an easy way to search an XML document using java. It is much more convenient than having to crawl through the document tree using the DOM API. XQuery builds on XPath and provides an SQL-like language for querying XML documents. It is also capable of updating and modifying the XML document, something which XPath cannot do. In this article, we present a beginner’s introduction to XQuery and how to use it from java.

To use XQuery from java, you need to install the appropriate jars and setup your environment. We have covered details of how to install and use Oracle’s XQuery Processor for java here. Follow those instructions to get XQuery installed properly.

2. Running XQuery Snippets from Java

The following sample class shows how to setup the XQuery processor to be used for searching XML.

public class sample1
{
    private static class MyEntityResolver extends OXQEntityResolver {
        @Override
        public OXQEntity resolveEntity(OXQEntityKind kind,
                                       OXQEntityLocator locator,
                                       OXQEntityResolverRequestOptions options)
            throws java.io.IOException
        {
            if (kind == OXQEntityKind.DOCUMENT) {
                URI systemId = locator.getSystemIdAsURI();
                if ("file".equals(systemId.getScheme())) {
                    File file = new File(systemId);
                    FileInputStream input = new FileInputStream(file);
                    OXQEntity result = new OXQEntity(input);
                    result.enlistCloseable(input);
                    return result;
                }
            }
            return null;
        }
    }

    static private String runQuery(String query)
        throws javax.xml.xquery.XQException
    {
        XQConnection con = null;
        XQPreparedExpression expr = null;
        XQSequence result = null;
        try {
            OXQDataSource ds = new OXQDataSource();
            con = ds.getConnection();
            OXQView
                .getConnection(con)
                .setEntityResolver(new MyEntityResolver());
            XQStaticContext ctx = con.getStaticContext();
            ctx.setBaseURI(Paths.get("").toUri().toString());
            expr = con.prepareExpression(query, ctx);
            result = expr.executeQuery();
            return result.getSequenceAsString(null);
        } finally {
            if ( result != null ) result.close();
            if ( expr != null ) expr.close();
            if ( con != null ) con.close();
        }
    }
}

3. Some XQuery Examples

We use the sample XML file books.xml from here:

<?xml version="1.0"?>
<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications
      with XML.</description>
   </book>
   <book id="bk102">
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
...

To run a query in a String, invoke the runQuery() method. It returns the result of the execution, which can be printed or saved.

Note that XQStaticContext.setBaseURI() has been invoked to resolve local files from the current directory. This means XML documents are located with respect to the current directory.

3.1. Print the Whole XML Document

The following prints the whole XML document books.xml in the current directory.

System.out.println(runQuery("doc('books.xml')"));

Output:

<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications
      with XML.</description>
   </book>
   <book id="bk102">
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
...

3.2. Select all books whose price is greater than 30

XQuery:

doc("books.xml")/catalog/book[price > 30]

Output:

<book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications
      with XML.</description>
   </book><book id="bk110">
      <author>O'Brien, Tim</author>
      <title>Microsoft .NET: The Programming Bible</title>
      <genre>Computer</genre>
      <price>36.95</price>
...

3.3. Using the XPath Function position()

The following example illustrates the use of the XPath function position() – selecting the first three book elements.

doc('books.xml')/catalog/book[position() < 3]

Output:

<book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications
      with XML.</description>
   </book><book id="bk110">
      <author>O'Brien, Tim</author>
      <title>Microsoft .NET: The Programming Bible</title>
      <genre>Computer</genre>
      <price>36.95</price>
...

3.4. Select the last() matching element

XQuery:

doc('books.xml')/catalog/book[last()]

Output:

<book id="bk112">
      <author>Galos, Mike</author>
      <title>Visual Studio 7: A Comprehensive Guide</title>
      <genre>Computer</genre>
      <price>49.95</price>
      <publish_date>2001-04-16</publish_date>
      <description>Microsoft Visual Studio 7 is explored in depth,
      looking at how Visual Basic, Visual C++, C#, and ASP+ are
      integrated into a comprehensive development
      environment.</description>
   </book>

3.5. Used as a HTML templating language with an XML Data Source

The following generates HTML output from the input template by executing the XQuery expression within {}. Each book element serves as the context node for the for loop.

<html>
<body>
<h1>Bookstore</h1>
<ul>
{
        for $x in doc("books.xml")/catalog/book
        order by $x/title
        return <li class="{data($x/genre)}">{data($x/title)}</li>
}
</ul>
</body>
</html>

Output:

<html><body><h1>Bookstore</h1><ul><li class="Horror">Creepy Crawlies</li><li class="Romance">Lover Birds</li><li class="Computer">MSXML3: A Comprehensive Guide</li><li class="Fantasy">Maeve Ascendant</li><li class="Computer">Microsoft .NET: The Programming Bible</li><li class="Fantasy">Midnight Rain</li><li class="Fantasy">Oberon's Legacy</li><li class="Science Fiction">Paradox Lost</li><li class="Romance">Splish Splash</li><li class="Fantasy">The Sundered Grail</li><li class="Computer">Visual Studio 7: A Comprehensive Guide</li><li class="Computer">XML Developer's Guide</li></ul></body></html>

3.6. Changing the XML Structure

This example illustrates a FLWOR clause which picks out the title and wraps the output in a different XML element.

for $x in doc("books.xml")/catalog/book return <book>{upper-case($x/title)}</book>

Output:

<book>XML DEVELOPER'S GUIDE</book><book>MIDNIGHT RAIN</book><book>MAEVE ASCENDANT</book><book>OBERON'S LEGACY</book><book>THE SUNDERED GRAIL</book><book>LOVER BIRDS</book><book>SPLISH SPLASH</book><book>CREEPY CRAWLIES</book><book>PARADOX LOST</book><book>MICROSOFT .NET: THE PROGRAMMING BIBLE</book><book>MSXML3: A COMPREHENSIVE GUIDE</book><book>VISUAL STUDIO 7: A COMPREHENSIVE GUIDE</book>

3.7. Grouping titles by author

This example shows you how to do more complex manipulation of the nodes. Here, we select distinct author elements and assemble a grouping of book titles by author.

let $books := doc("books.xml")/catalog/book
for $author in distinct-values($books/author)
return <author name="{ $author }">{$books[author = $author]/title}</author>

Output:

<author name="Gambardella, Matthew"><title>XML Developer's Guide</title></author><author name="Ralls, Kim"><title>Midnight Rain</title></author><author name="Corets, Eva"><title>Maeve Ascendant</title><title>Oberon's Legacy</title><title>The Sundered Grail</title></author><author name="Randall, Cynthia"><title>Lover Birds</title></author><author name="Thurman, Paula"><title>Splish Splash</title></author><author name="Knorr, Stefan"><title>Creepy Crawlies</title></author><author name="Kress, Peter"><title>Paradox Lost</title></author><author name="O&apos;Brien, Tim"><title>Microsoft .NET: The Programming Bible</title><title>MSXML3: A Comprehensive Guide</title></author><author name="Galos, Mike"><title>Visual Studio 7: A Comprehensive Guide</title></author>

Conclusion

And that is a beginner’s tutorial to using XQuery from within Java. We learnt how to run XQuery code from a String. We also covered some examples illustrating conditionals, use of XPath functions, text templating with XML data sources and grouping with XQuery.