XQuery Update Extension
(1Q18)
This article describes eXist-db's extension to XQuery for updating nodes in the database.
Important Considerations
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"]
update insert attribute type {'permanent'} into //address[fname="Andrew"]
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>
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'
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
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'