Loading TOC...
XQuery and XSLT Reference Guide (PDF)

XQuery and XSLT Reference Guide — Chapter 3

MarkLogic Server Enhanced XQuery Language

The default XQuery dialect in MarkLogic Server is enhanced. (1.0-ml) The enhanced dialect includes all of the features in the strict XQuery 1.0 dialect, and adds several other features to make it easier to use XQuery as a programming language with which to create applications. This chapter describes the features of the enhanced dialect and includes the following sections:

For details on the XQuery language, see XQuery Language and the W3C XQuery specification (http://www.w3.org/TR/xquery/).

try/catch Expression

The try/catch extension allows you to catch and handle exceptions. MarkLogic Server exceptions are thrown in XML format, and you can apply an XPath statement to the exception if there is a particular part you want to extract. The exception is bound to the variable in the catch clause.

The following code sample uses a try/catch block to catch exceptions upon loading a document, and prints out the filename if an exception occurs.

try {
     let $filename := "/space/myfile.xml"
     let $options := <options xmlns="xdmp:document-load">
                         <uri>/myfile.xml</uri>
                         <repair>none</repair>
                      </options>
     return xdmp:document-load($filename, $options)
     }
catch ($exception) {
"Problem loading file, received the following exception: ",
$exception }

Most exceptions can be caught with a try/catch block, but the XDMP-CANCELED, SVC-CANCELED, and XDMP-DISABLED exceptions cannot be caught in a try/catch block.

Function Mapping

Function mapping is an extension to XQuery that allows you to pass a sequence to a function parameter that is typed to take a singleton item, and it will invoke that function once for each item in the sequence. This section describes function mapping and includes the following parts:

Understanding Function Mapping

Function mapping is equivalent to iterating over the sequence like it was in a for clause of a FLWOR expression. The following is an example of function mapping:

xquery version "1.0-ml";

declare function local:print-word ($word as xs:string) { $word };

local:print-word( ("hello", "world") )
(: 
   evaluates the print-word function twice, once for "hello" 
   and once for "world", returning hello world 
:)

Function mapping also works on multiple singleton parameters, resulting in the cross product of all the values (equivalent to nested for clauses). In the case of multiple mappings, they occur left to right. For example, the following is evaluated like a nested for loop:

xquery version "1.0-ml";
(1 to 2) * (3 to 4)
(: returns the sequence (3, 4, 6, 8) :) 

One consequence of function mapping, which can be surprising the first time you see it, is that if the value passed for a parameter is the empty sequence, it could result in the function being called 0 times (that is, in the function never runs and results in the empty sequence. For example, if you entered the empty sequence as the parameter to the above function call, it returns empty, as follows:

xquery version "1.0-ml";

declare function local:print-word ($word as xs:string) { $word };

local:print-word( () )
(: 
   evaluates the print-word function zero times, resulting 
   in the empty sequence
:)

The local:print-word function is never called in this case, because it is iterating over the empty sequence, which causes zero invocations of the function. If your function calls are fed by code that can return the empty sequence (an XPath expression, for example), then you might see this behavior.

Enabling or Disabling Function Mapping

In 1.0-ml, function mapping is enabled by default. In 1.0, it is disabled by default. You can enable it in 1.0 by adding the following to the XQuery prolog:

declare namespace xdmp="http://marklogic.com/xdmp";
declare option xdmp:mapping "true";

Similarly, you can explicitly disable function mapping in 1.0-ml by adding the following to the prolog:

declare option xdmp:mapping "false";

You cannot use function mapping in the 0.9-ml dialect; if you run code expecting it to map singletons to a sequence in 0.9-ml (or in 1.0 or 1.0-ml if function mapping is diabled), it will throw an exception because the sequence cannot be cast to a single string.

Semi-Colon as Transaction Separator

In the enhanced dialect, you can add a semi-colon after one or more XQuery statements in the body of a main module and then add another one or more XQuery statement. The two sets of statements are then evaluated as two separate transactions. Each set of statements must be a main module; that is, they must all have their own prolog elements. All of the statements in the program must use the same XQuery dialect. For example, the following creates a document and then returns the contents of the document:

xquery version "1.0-ml";
xdmp:document-insert("/mydocs/sample.xml", 
            <some-element>content</some-element>) ;
xquery version "1.0-ml";
(: Note that the XQuery version must be the same for all 
   statements in the module :)
fn:doc("/mydocs/sample.xml")
(: returns the document created in the previous statement :)

Note that you cannot use the semi-colon as a transaction separator in the strict XQuery dialect (1.0). For more details on transactions, see Understanding Transactions in MarkLogic Server chapter in the Application Developer's Guide.

Private Function and Variable Definitions

In the 1.0-ml enhanced dialect, you can create library modules with functions and variables that are private to the library module. Private functions and variables are useful when you have certain code you do not want to expose to users of the library, but might be useful for functions for the library to use. To make functions and variables private, add private to the function or variable declaration syntax as follows:

declare private function ....
declare private variable ....

Note that functions and variables in a main module are private by definition, so declaring them private only makes sense for library modules.

Functions With Side Effects

The XQuery specification defines that XQuery programs produce only their return values, without producing any side effects; that is, without causing any changes to the run-time environment as a result of running the program (with the exception of fn:trace). MarkLogic Server has many enhancements that cause side effects. For example, there are functions that insert or update documents in a database. Since functions like the ones that update documents do more than functions that simply return values, they are extensions to the XQuery specification.

Side effects are extremely useful when building applications. Therefore, MarkLogic Server includes many functions that have side effects. The following are some examples of functions with side effects:

Shorthand Positional Predicate Syntax

MarkLogic Server enhanced mode supports the shorthand version of the positional predicate syntax, where you can specify the position numbers to include. For example, the following specifies the first three items in the sequence:

xquery version "1.0-ml";
(1, 2, 3, 4, 5, 5)[1 to 3]

In XQuery 1.0 strict mode (1.0), you must use the fn:position() function as in the following example:

xquery version "1.0";
(1, 2, 3, 4, 5, 5)[fn:position() = (1 to 3)]

Binary Node Constructor and Node Test

MarkLogic Server enhanced mode extends the XQuery types to include a binary node type. Binary nodes are used to store binary documents. To support this type, the MarkLogic Server enhanced XQuery dialect includes a node constructor (binary) to construct a binary node and a node test (binary()) to test whether a node is a binary node (for example, in a typeswitch expression). These extensions are not available in the 1.0 dialect.

validate as Expression

In the 1.0-ml dialect, you can use the validate as syntax to specify the type for a validate expression. The validate as expression is an extension to the XQuery 1.0 validate expression, and it is only available in 1.0-ml; it is not available in the 1.0 dialect. For details on the validate expression, see Validate Expression.

Serialization Options

You can set the serialization options in XQuery with the declare option XQuery prolog. In XSLT, you can set the serialization options using the <xsl:output> instruction. For details on setting the serialization options in XQuery, see Declaring Options. For XSLT output details, see the XSLT specification (http://www.w3.org/TR/xslt#output).

Importing a Stylesheet Into an XQuery Module

Using the 1.0-ml dialect, you can import a XSLT stylesheet into an XQuery module, allowing you access to the functions and variables defined defined by that stylesheet. To import a stylesheet in XQuery, use a prolog expression of the following form:

import stylesheet at "/path-to-stylesheet.xsl";

The following example shows an XQuery module that imports a stylesheet and runs a function in the stylesheet:

xquery version "1.0-ml";

(: assumes a stylesheet at /f.xsl with the following contents:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   version="2.0" 	xmlns:foo="foo">
	<xsl:function name="foo:foo">foo</xsl:function>
</xsl:stylesheet>
:)

import stylesheet at "/f.xsl";
declare namespace foo="foo";

foo:foo()

(: Returns the string:
foo 
which is the output of the 
stylesheet function. :)

Similarly, you can import an XQuery module into an XSLT stylesheet, as described in Importing XQuery Function Libraries to a Stylesheet.

To use functions and variables from a stylesheet in XQuery, they should be defined in a namespace in the stylesheet. In XQuery, it is difficult to call functions and variables in no namespace. Therefore, the best practice is, for functions and variables in a stylesheet that you plan to import into an XQuery module, define them in a namespace. Note that in an XQuery library module, all function and variable declarations must be in a namespace.

Implementation-Defined Semantics

The XQuery specification lists a number of items that are allowed to be defined by each implementation of XQuery:

http://www.w3.org/TR/xquery/#id-impl-defined-items

This section describes the following implementation-defined items as they are implemented in MarkLogic Server:

Automatic Namespace Imports for Predefined Namespaces

Each dialect has a set of namespace prefixes that are predefined. For those predefined namespaces, it is not necessary to declare the prefix. For example, the fn prefix is predefined in all of the dialects. For a list of predefined namespaces for each dialect, see Predefined Namespace Prefixes for Each Dialect.

The fn: prefix is bound to a different namespace in 1.0 and 1.0-ml than in 0.9-ml.

External Variables

External variables are one of the things that the XQuery standard refers to as implementation-defined. In MarkLogic Server, external variables are implemented such that you can pass nodes and values into an XQuery program. To use external variables, you pass in external variables to the XQuery program (via xdmp:invoke, xdmp:eval, xdmp:spawn, or via XCC). The variables are passed in as pairs of QNames and values.

An XQuery program that accepts external variables must declare the external variables in its prolog, as in the following code snippet:

declare variable $my:variable as xs:string* external;

You can create a default value for the variable by adding the := to the specification, as in the following code snippet:

declare variable $my:variable as xs:string* external 
  := "default value";

An XQuery program with this variable declaration would be able to use the string values passed into it via an external variable with the QName my:variable (where the namespace prefix my was declared somewhere in both the calling and called environments). You could then reference this variable in the XQuery program as in the following example:

xquery version "1.0-ml";
declare namespace my="myNamespace";
declare variable $my:variable as xs:string* external;

fn:concat("The value of $my:variable is: ", $my:variable)

If you then call this module as follows (assuming the module can be resolved from the path /extvar.xqy.

xquery version "1.0-ml";
declare namespace my="myNamespace";

xdmp:invoke("/extvar.xqy", (xs:QName("my:variable"), "my value"))

This example returns the following string:

The value of $my:variable is: my value

Collations

The XQuery specification allows collation names and default collation values to be determined by the implementation. MarkLogic Server uses collations to specify the sort order of strings, and it defines the URIs for the collations. Each query runs with a default collation, and that collation can come from the environment (each App Server has a default collation setting) or it can be specified in the XQuery program. Also, you can specify collations for string range indexes and for word lexicons to specify their sort order. For details about collations in MarkLogic Server, including the valid URIs for collations, see Encodings and Collations in the Search Developer's Guide.

Implementation-Defined Primitive XQuery Types

MarkLogic Server has extended the XQuery type system and added some primitive types. These types allow functions to operate on them and are very useful for programming. These types are not required by the XQuery specification, but neither are they in conflict with it because the specification allows implementation-specific primitive types. Therefore, these types are available in all of the XQuery dialects in MarkLogic Server (although in 1.0, you need to import the namespace prefixes). The following are some of the built-in types in MarkLogic Server:

Decimal Precision at Least 18 Digits, and is Not Configurable

MarkLogic Server does not include a facility to limit the maximum precision of a decimal. A decimal has a precision of at least 18 decimal digits (64-bits unsigned). For details, see the XML Schema specification (http://www.w3.org/TR/xmlschema-2/#decimal).

Library Modules Default Function Namespace Defaults to Library Namespace

The default function namespace of an XQuery library module is the namespace of the library module. This allows you to declare functions in the library namespace without prefixing the functions. You can override the default function namespace with a declare default function namespace declaration in the prolog of the library module. For library modules where you do not override the default function namespace (and as a general best-practice), you should prefix the XQuery-standard functions (functions with the fn: prefix, which is bound to the http://www.w3.org/2005/xpath-functions namespace) with the fn: prefix. Note that main modules default function namespace defaults to the fn: namespace, which is different from library modules.

« Previous chapter
Next chapter »