Using XQuery from C#

Note that the current version of SaxonCS offers "enterprise edition" capability only.

You can perform a query using the Saxon.Api interface as follows:

  1. Create a Processor and set any global configuration options on the Processor.

  2. Optionally, build the source document by calling NewDocumentBuilder() to create a document builder, setting appropriate options, and then calling one of the Build() methods. This returns an XdmNode which can be supplied as input to the query either as the context item, or as the value of an external variable.

  3. Call NewXQueryCompiler() to create an XQueryCompiler. Then set any options that are local to a specific compilation (for example, the destination of error messages, the base URI, or the character encoding of the query text).

  4. Call one of the Compile() methods to compile a query. The result is an XQueryExecutable, which can be used as often as you like in the same thread or in different threads.

  5. To run a query, first call the Load() method on the XQueryExecutable. This creates an XQueryEvaluator. The XQueryEvaluator can be serially reused, but it must not be shared across multiple threads. Set any options required for the specific query execution (for example, the initial context node, the values of external variables, and the destination for the query result), and then call any of the methods Evaluate(), EvaluateSingle(), Run(), RunStreamed(), or GetEnumerator() methods to execute the query.

  6. Because the XQueryEvaluator is an IEnumerable, it is possible to iterate over the results directly using the C# "foreach" construct:

    foreach(XdmItem item in compiler.Compile("1 to 10").Load()) {...}

  7. The result of the XQueryEvaluator.Evaluate() method is an XdmValue. Saxon provides powerful facilities (modeled on LINQ) to process an XdmValue using steps and predictaes. For example, if the query returns a single node section, (XdmNode is a subclass of XdmValue), then you could test whether it has any descendant para elements with @class="normal" by writing

    if (section.Select(Descendant("para").Where(Eq(Attribute("class"), "normal")).Exists()) {...}

The output of the query may be retrieved as an iterator over a sequence of items, or it may be specified as an IDestination object, which allows a wide range of possibilities. The most common IDestination is a Serializer, which can format the result as XML, HTML, or JSON. Alternatively, you can build a tree either in Saxon's native format (represented by the class Saxon.Api.XdmNode) or as a DOM.

Examples of C# queries are included in the saxon-resources file, see module APIExamples.cs.

Separate compilation of library modules

Under Saxon-EE, it is possible to compile library modules separately from the main module. This reduces the compilation time and memory usage when the same library module is imported by many main modules for different queries. A method CompileLibrary() (with a number of overloaded variants supplying the input in different ways) is provided in the XQueryCompiler class; any library module compiled using this method will be available to all subsequent compilations using the same XQueryCompiler. To import the module, simply use import module specifying the module URI in the normal way. It is not necessary to supply a module location hint (at "URI"), and if any is supplied, it will be ignored.