Chapter 5. Programming with the Qizx/open API
Prev | Part III. Developer's Guide | Next

## Chapter 5. Programming with the Qizx/open API

The API in Qizx/open is much simpler than in Qizx because it has not to deal with the management of XML libraries. This section is a simplified version of the tutorial found in ???.

## 1. Compiling and running the code samples

The code samples used to illustrate this chapter (class `OpenQuery.java`) are found in the `docs/samples/programming/qizxopen` directory. Files containing XQuery scripts are found in the `docs/samples/programming/qizxopen/queries` sub-directory. These scripts are almost the same as those used in the Qizx tutorial, except that access to documents is performed through file paths instead of locations within an XML Library.

You'll need a recent version of ant, a Java-based build tool to compile and run the codes samples.

## 2. Creating a work session

To create a XML Query session, we need a factory, which is an instance of the class `XQuerySessionManager`. This class manages documents and XML Query modules, so it is recommended to use a single instance from which all sessions are created. The argument of the constructor is an URL used to locate XQuery modules: here it points to the current directory, but we could also use an HTTP URL pointing to a network server.

     File currentDir = new File(System.getProperty("user.dir"));
     XQuerySessionManager sm = new XQuerySessionManager(currentDir.toURL());

     XQuerySession session = sm.createSession();

### Tuning the document cache:

If you have to handle large documents or many documents in a Qizx/open application, it can be useful to tune the size of the document cache. This cache keeps the last documents parsed, so it avoids reloading documents in different sessions. However the cache detects a modification on a document in a file and reloads it.

Reminder: in Qizx/open, documents are always parsed into memory before processing. The functions that load documents are `doc()` and `collection()`. They are documented in the last section of this appendix: ???.

Use `XQuerySessionManager.setTransientDocumentCacheSize(int size)` to specify a size in bytes for this cache. You can also use the system property `com.qizx.docpool.maxsize` (For example you would specify `-Dcom.qizx.docpool.maxsize=100000000` on the command line).

## 3. Compiling and executing queries

Compiling and running a XML Query script is fairly easy:

    Expression expr = session.compileExpression(script);
    ItemSequence results = expr.evaluate();
    while (results.moveToNextItem()) {
        Item result = results.getCurrentItem();

        /*Do something with result.*/
    }

| First compile an XQuery expression using `XQuerySession.compileExpression`. The argument `script` contains a XQuery query expression as a string. If no compilation errors (`CompilationException`) are found, this returns an `Expression` object.
| Then evaluate the expression using `Expression.evaluate`. If no evaluation errors (`EvaluationException`) are found, this returns the results of the evaluation in the form of an `ItemSequence`.
| An `ItemSequence` allows to iterate over a sequence of `Item`s (see ???). A `Item` is either an atomic value or an XML `Node`. Example (`1.xq`):
    (: Compute and return 2 + 3 :)
    2 + 3
evaluates to an `ItemSequence` containing a single atomic value (5). Example (`3.xq`):
    (: List all books by their titles. :)
    declare namespace t = "http://www.qizx.com/namespace/Tutorial";

    collection("../../book_data/Books/*.xml")//t:book/t:title
evaluates to an `ItemSequence` containing several `t:title` element `Node`s.

The `OpenQuery` class implements a simple command-line tool allowing to run queries.

Excerpts of `OpenQuery.java`:

        private static Expression compileExpression(XQuerySession session,
                                                    String script,
                                                    QName[] varNames,
                                                    String[] varValues)
            throws IOException, QizxException
        {
            Expression expr;
            try {
                expr = session.compileExpression(script);
            }
            catch (CompilationException e) {
                Message[] messages = e.getMessages();
                for (int i = 0; i < messages.length; ++i) {
                    error(messages[i].toString());
                }
                throw e;
            }

            if (varNames != null) {
                for (int i = 0; i < varNames.length; ++i) {
                    expr.bindVariable(varNames[i], varValues[i], /*type*/ null);
                }
            }

            return expr;
        }

| An XQuery expression can be further parametrized by the use of variables. Example (`101.xq`):
    (: List all books containing the value of variable $searched
       in their titles. :)
    declare namespace t = "http://www.qizx.com/namespace/Tutorial";

    declare variable $searched external;

    collection("/Books")//t:book/t:title[contains(., $searched)]
`Expression.bindVariable` allows to give a variable its value, prior to evaluating the expression.

Some queries may return thousands of results. Therefore, displaying just a range of results (e.g from result #100 to result #199 inclusive) is a very common need.

        private static void evaluateExpression(Expression expr,
                                               int from, int limit)
            throws QizxException {
            ItemSequence results = expr.evaluate();
            if (from > 0) {
                results.skip(from);
            }

            XMLSerializer serializer = new XMLSerializer();
            serializer.setIndent(2);

            int count = 0;
            while (results.moveToNextItem()) {
                Item result = results.getCurrentItem();

                System.out.print("[" + (from+1+count) + "] ");
                showResult(serializer, result);
                System.out.println();

                ++count;
                if (count >= limit)
                    break;
            }
            System.out.flush();
        }

| `ItemSequence.skip` allows to quickly skip the specified number of `Item`s.
| This being done, you still need to limit the number of `Item`s you are going to display.

In this lesson, we'll just show how to print the string representation of an `Item`.

        private static void showResult(XMLSerializer serializer,
                                       Item result)
            throws QizxException {
            if (!result.isNode()) {
                System.out.println(result.getString());
                return;
            }
            Node node = result.getNode();

            serializer.reset();
            String xmlForm = serializer.serializeToString(node);
            System.out.println(xmlForm);
        }

| `Item.isNode` returns `true` for a `Node` and `false` for an atomic value. Similarly, `Item.getNode` returns a `Node` when the `Item` actually is a Node and `null` when the `Item` is an atomic value.
| `Item.getString` returns the string value of an `Item` (whether `Node` or atomic value). What precisely is the string value of an `Item` is specified in the XQuery standard.
| The `XMLSerializer.serializeToString` convenience method is used to obtain the string representation of a `Node`.

### 3.1. Compiling and running the code of this lesson

- Compile class `Query` by executing ant (see `build.xml`) in the `docs/samples/programming/query/` directory.

- Run ant run1 in the `docs/samples/programming/qizxopen/` directory to perform this query:

      (: Find all books written by French authors. :)
      declare namespace t = "http://www.qizx.com/namespace/Tutorial";

      for $a in collection("/Authors")//t:author[@nationality = "France"]
          for $b in collection("/Books")//t:book[.//t:author = $a/t:fullName]
          return
              $b/t:title

  You can execute all the queries by running ant run_all in `docs/samples/programming/qizxopen/`.

Prev | Up | Next
Part III. Developer's Guide | Home | Part IV. Reference