Updating Documents with XQUF

The primitives are insert node (into, as first into, before, after), delete node, replace node, replace value of node and rename node. On a database they change the data; on a file, update a copy with copy ... modify ... return. Run basex -i booknest-catalog.xml restock.xq:

restock.xq: five updates applied to a copy of one book
(: XQUF on a copy: the stored catalog is not touched :)
copy $b := //book[@id = "b3"]
modify (
  replace value of node $b/supply/availability with "in-stock",
  replace value of node $b/supply/price with "26.00",
  insert node <format>hardcover</format> after $b/pages,
  delete node $b/summary,
  rename node $b/rating as "stars"
)
return $b/(*[position() = 5 to 8], .//price)
Output
<pages>256</pages>
<format>hardcover</format>
<published>2023</published>
<stars>4.8</stars>
<price currency="USD">26.00</price>

Select new elements by position: count($b/format) gave 0 on BaseX 12.4 693,830 , answered from the source's index.


XQUF

XQuery Update Facility (XQUF) is an extension to XQuery for updating XML documents in place, via insert, delete, replace, and rename expressions, a copy-modify-return transform expression, and an inline update expression usable inside a FLWOR. BaseX 693,830 is a program that supports XQUF.

Each example below updates the following document independently:
ch05-xquf-data.xmlXML
merged-01-01-ch05-xquf-data.xml
<?xml version="1.0" encoding="UTF-8" ?>
<a>
   <b>Hello</b>
   <b>World</b>
</a>

insert node

The insert node expression adds one or more nodes into, before, or after a target node. Inserting a sequence of an attribute, a text node, and an element into /a appends them as the last children (attributes are added to the element regardless of position):
ch05-xquf-insert-into.xq
insert node (attribute {'id'}{5},'Yes!',<c/>) into /a
as first into inserts a node as the first child of the target instead of the last (as last into is equivalent to a plain into):
ch05-xquf-insert-first.xq
insert node <c/> as first into /a
(: 'as last into' can be used too :)
Output
<a>
  <c/>
  <b>Hello</b>
  <b>World</b>
</a>
before inserts a node as the preceding sibling of a target node (after inserts it as the following sibling):
ch05-xquf-insert-before.xq
insert node <c/> before /a/b[2]
(: 'after' can be used too :)
Output
<a>
  <b>Hello</b>
  <c/>
  <b>World</b>
</a>

delete node

Removes one or more target nodes from the document:
ch05-xquf-delete.xq
delete node (a/b[1],a/b[2])
Output
<a/>

replace node

Replaces a target node with a new node, including its name and content:
ch05-xquf-replace-node.xq
replace node a/b[2] with <c>Kitty</c>
Output
<a>
  <b>Hello</b>
  <c>Kitty</c>
</a>
replace value of node keeps the target node's name and only replaces its value, so the replacement expression's string value becomes the new content while the element name stays unchanged:
ch05-xquf-replace-value.xq
replace value of node a/b[2] with <c>Kitty</c>
Output
<a>
  <b>Hello</b>
  <b>Kitty</b>
</a>

rename node

Changes the name of a target node, keeping its content:
ch05-xquf-rename.xq
rename node a/b[1] as 'x'
Output
<a>
  <x>Hello</x>
  <b>World</b>
</a>

transform expression: copy ... modify ... return

A copy-modify-return expression binds a variable to a copy of a node, applies a sequence of update expressions to that copy inside modify, and returns the modified copy without touching the original document:
ch05-xquf-transform.xq
copy $v := /a
modify (
  rename node $v/b[1] as 'c',
  insert node ('Kitty') into $v/b[2]
) return $v
Output
<a>
  <c>Hello</c>
  <b>WorldKitty</b>
</a>

update expression

An update expression applies update expressions to a node inline, e.g. within the return clause of a for, without a separate copy-modify-return block:
ch05-xquf-update-expr.xq
for $v in a/b
return $v update delete node text()
Output
<b/>
<b/>

Updating functions

A user-defined function can be marked as updating with the %updating annotation, allowing it to perform update expressions in its body: declare %updating function local:f() {...}. An updating function returns the "pending update list" of changes it makes rather than a regular value.