XQuery Update Extension

(2Q19)


This article describes eXist-db's extension to XQuery for updating nodes in the database.

Important Considerations

Two things you should take into account with respect to the updating extension.

Relationship to W3C Recommendation

This extension was created well before the W3C working group created the XQuery Update Facility 1.0 recommendation and therefore differs substantially from it.

Persistent Document Updates

The XQuery update extension was designed for updating persistent documents stored in the database. It does not work for updating temporary document fragments constructed within an query.

For example:

let $node := <root><a/></root>
return 
    update insert <b/> into $node/a

Since $node is an in-memory constructed element (rather than a node stored in the database) the query has no effect and simply returns the empty element.

Update Syntax

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 an update expression is empty-sequence().

An update statement may occur at any position within the XQuery main code or a function body.

Warning:

When using update within the return clause of a FLWOR expression, be cautious when deleting or replacing nodes that are still being used by the enclosing code. This is because a delete or replace will be processed immediately, and so the deleted or replaced node will no longer be available to the query. Such actions can corrupt the database!

For example, the following expression will throw the database into an inconsistent state if //address returns more than one node:

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

However, an expression like the following is safe as it only modifies the current iteration variable. The following example only deletes $address (the current iteration variable) instead of //address (all addresses in the database):

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

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 must 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.

update insert <email type="office">andrew@gmail.com</email> into //address[fname="Andrew"]
Insert Example: Element
update insert attribute type {'permanent'} into //address[fname="Andrew"]
Insert Example: Attribute

Replace

update replace expr with exprSingle

Replaces the nodes returned by expr with the nodes in exprSingle. expr must evaluate to a single element, attribute or text node. If it is an element, exprSingle must contain a single element node. 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 exprSingle. expr cannot be the root element of a document.

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

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.

update value //fname[. = "Andrew"] with 'Andy'
Value Example

Delete

update delete expr

Removes all nodes in expr from their document. expr cannot be the root element of a document.

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

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. expr cannot be the root element of a document.

for $city in //address/city 
return
    update rename $city as 'locale'
Rename Example