XQuery Update Extensions

Previous versions of eXist already offered some functions to execute XUpdate queries from within XQuery. However, this approach had its limitations, mainly due to the lack of integration between the XUpdate language and XQuery. XUpdate operations are specified in XML and the XUpdate processor uses its own instance of the query engine. To forward information from the XQuery to the XUpdate, one had to dynamically construct an XUpdate XML fragment, passing the required XPath expressions as strings.

We thus provide an extension to XQuery, which maps each of the XUpdate instructions to a corresponding XQuery expression. Until the W3C working group starts its work on an official update specification, the basic syntax follows the proposal by Patrick Lehti.

Important

The XQuery update extension has been designed to simplify updates on persistent documents stored in the database. However, it is not suitable for updating temporary document fragments constructed within the XQuery, i.e. you can't use it to modify the results returned by a query. For example, the following query has no visible effect because it operates on an in-memory fragment:

let $doc := <root><a/></root>
return (update insert <b/> into $doc/a, $doc)

The query just ignores the update and returns the constructed root element (it would probably be less confusing if the query would just throw an exception. We may have to change that ...)

All update statements start with the keyword "update", followed by an update action. Available actions are: "insert", "delete", "replace", "value" and "rename". The return type of the expression is empty().

An update statement may occur at any position within the XQuery main code or a function body. When using an update within the return clause of a FLWOR expression, it should be clear that one should not delete or replace nodes that are still being used by enclosing code. A delete or replace will be processed immediately, and the deleted or replaced node will no longer be available. For example, the following expression throws the db into an inconsistent state if //address returns more than one node:

Example: Bad Update

for $address in //address
return
    update delete //address

However, an expression like the following is save as it only modifies the current iteration variable:

Example: Complex Update

for $address in //address
return
    (: Move lname and fname into a new name element :)
    update replace $address with
        <address>
            <name>
                <family>{$address/lname/text()}</family>
                <given>{$address/fname/text()}</given>
            </name>
            {$address/city, $address/email}
        </address>

1. Insert

update insert expr ( into | following | preceding )
exprSingle

Inserts the content sequence specified in expr into the element node passed via exprSingle. exprSingle and expr should evaluate to a node set. If exprSingle contains more than one element node, the modification will be applied to each of the nodes. The position of the insertion is determined by the keywords "into", "following" or "preceding":

into

The content is appended after the last child node of the specified elements.

following

The content is inserted immediately after the node specified in exprSingle.

preceding

The content is inserted before the node specified in exprSingle.

Example: Insert Example

update insert <email type="office">andrew@gmail.com</email> into //address[fname="Andrew"]

2. Replace

update replace expr with exprSingle

Replaces the nodes returned by expr with the nodes in exprSingle. expr may evaluate to a single element, attribute or text node. If it is an element, exprSingle should contain a single element node as well. If it is an attribute or text node, the value of the attribute or the text node is set to the concatenated string values of all nodes in expr.

Example: Replace Example

update replace //fname[. = "Andrew"] with <fname>Andy</fname>

3. Value

update value expr with exprSingle

Updates the content of all nodes in expr with the items in exprSingle. If expr is an attribute or text node, its value will be set to the concatenated string value of all items in exprSingle.

4. Delete

update delete expr

Removes all nodes in expr from their document.

Example: Delete Example

for $city in //address/city return update delete $city

5. Rename

update rename expr as exprSingle

Renames the nodes in expr using the string value of the first item in exprSingle as the new name of the node. expr should evaluate to a set of elements or attributes.