[41] | ExprSingle |
::= | FLWORExpr |
[108] | SimpleMapExpr |
::= | PathExpr ("!" PathExpr)* |
XQuery Update Facility 3.0 adds eight new kinds of expressions. The syntax and semantics of these expressions are described in the following sections.
[200] | InsertExpr |
::= | "insert" ("node" | "nodes") SourceExpr InsertExprTargetChoice TargetExpr |
[199] | InsertExprTargetChoice |
::= | (("as" ("first" | "last"))? "into") |
[204] | SourceExpr |
::= | ExprSingle |
[205] | TargetExpr |
::= | ExprSingle |
An insert expression inserts copies of zero or more nodes into a
designated position with respect to a target node. The keywords node
and nodes
may be used interchangeably, regardless of how many nodes are actually inserted.
The position of the inserted nodes is determined as follows:
If before
(or after
) is specified:
The inserted nodes become the preceding (or following) siblings of the target node.
If multiple nodes are inserted by a single insert expression, the nodes remain adjacent and their order preserves the node ordering of the source expression.
If multiple groups of nodes are inserted by multiple insert expressions in the same snapshot, adjacency and ordering of nodes within each group is preserved but ordering among the groups is implementation-dependent.
If as first into
(or as last into
) is specified:
The inserted nodes become the first (or last) children of the target node.
If multiple nodes are inserted by a single insert expression, the nodes remain adjacent and their order preserves the node ordering of the source expression.
If multiple groups of nodes are inserted by multiple insert expressions in the same snapshot, adjacency and ordering of nodes within each group is preserved but ordering among the groups is implementation-dependent.
If into
is specified without as first
or as last
:
The inserted nodes become children of the target node.
If multiple nodes are inserted by a single insert expression, their order preserves the node ordering of the source expression.
The positions of the inserted nodes are chosen so as not to interfere with the intended
position of nodes that are inserted with the specification before
, after
,
as first into
, or as last into
. For example, If node B is inserted "after node A",
no other node will be inserted between nodes A and B unless it is also
inserted "after node A".
Subject to the above constraints, the positions of the inserted nodes among the children of the target node are implementation-dependent.
An insert expression is an updating expression.
The SourceExpr and TargetExpr can be expressions of any category.
SourceExpr is evaluated as though it were an enclosed
expression in an element constructor (see Rule 1e in Section
3.9.1.3 Content
XQ30). The result of this step is either an error or a
sequence of nodes to be inserted, called the insertion sequence. If the insertion sequence contains a document node, the document node is replaced
in the insertion sequence by its children. If the insertion sequence contains an attribute
node following a node that is not an attribute node, a type error is raised [err:XUTY0004]. Let $alist
be the sequence of attribute nodes in the insertion sequence. Let $clist
be the remainder of the insertion sequence, in its original order.
Note:
Either $alist
or $clist
or both may be empty.
TargetExpr is evaluated and checked as follows:
If the result is an empty sequence, [err:XUDY0027] is raised.
If any form of into
is specified,
the result must be a single element or document node; any other non-empty result raises
a type error [err:XUTY0005].
If before
or after
is specified, the result must be a single element, text, comment, or processing instruction
node; any other non-empty result raises a type error [err:XUTY0006].
If before
or after
is specified, the node returned by the target expression must have a non-empty parent
property [err:XUDY0029].
Let
$target
be the node returned by the target expression.
If $alist
is not empty and any form of into
is specified, the following checks are performed:
$target
must be an element node [err:XUTY0022].
No attribute node in $alist
may have a QName whose implied namespace binding conflicts with a namespace binding in the "namespaces" property of $target
[err:XUDY0023].
Multiple attribute nodes in $alist
may not have QNames whose implied namespace bindings conflict with each other [err:XUDY0024].
If $alist
is not empty and before
or after
is specified, the following checks are performed:
parent($target)
must be an element node [err:XUDY0030].
No attribute node in $alist
may have a QName whose implied namespace binding conflicts with a namespace binding in the "namespaces" property of parent($target)
[err:XUDY0023].
Multiple attribute nodes in $alist
may not have QNames whose implied namespace bindings conflict with each other [err:XUDY0024].
The result of the insert expression is an empty XDM instance and a pending update list constructed by merging the pending update lists returned by the SourceExpr and TargetExpr with the following update primitives using upd:mergeUpdates:
If as first into
is specified, the pending update list includes the following update primitives:
If $alist
is not empty, upd:insertAttributes($target, $alist)
If $clist
is not empty, upd:insertIntoAsFirst($target, $clist)
If as last into
is specified, the pending update list includes the following update primitives:
If $alist
is not empty, upd:insertAttributes($target, $alist)
If $clist
is not empty, upd:insertIntoAsLast($target, $clist)
If into
is specified with neither as first
nor as last
, the pending update list includes the following update primitives:
If $alist
is not empty, upd:insertAttributes($target, $alist)
If $clist
is not empty, upd:insertInto($target, $clist)
If before
is specified, let $parent
be the parent node of $target
. The pending update list includes the following update primitives:
If $alist
is not empty, upd:insertAttributes($parent, $alist)
If $clist
is not empty, upd:insertBefore($target, $clist)
If after
is specified, let $parent
be the parent node of $target
. The pending update list includes the following update primitives:
If $alist
is not empty, upd:insertAttributes($parent, $alist)
If $clist
is not empty, upd:insertAfter($target, $clist)
Insert a year
element after the publisher of the first book.
insert node <year>2005</year> after fn:doc("bib.xml")/books/book[1]/publisher
Navigating by means of several bound variables, insert a new police report into the list of police reports for a particular accident.
insert node $new-police-report as last into fn:doc("insurance.xml")/policies /policy[id = $pid] /driver[license = $license] /accident[date = $accdate] /police-reports
[201] | DeleteExpr |
::= | "delete" ("node" | "nodes") TargetExpr |
[205] | TargetExpr |
::= | ExprSingle |
A delete expression deletes zero or more nodes from an XDM instance.
The keywords node
and nodes
may be used interchangeably, regardless of how many nodes are actually deleted.
A delete expression is an updating expression.
The TargetExpr can be an expression of any category.
TargetExpr is evaluated. The result must be a
sequence of zero or more nodes; otherwise a type error is raised [err:XUTY0007].
Let $tlist
be the list of nodes returned by
the target expression.
If any node in $tlist
has no parent,
it is removed from $tlist
(and is thus ignored in the following step).
A new pending update list is created. For each node
$tnode
in $tlist
, the following
update primitive is appended to the pending update list:
upd:delete($tnode)
. The resulting pending update list
is merged with the pending update list returned
by the TargetExpr using upd:mergeUpdates, and
together with an empty XDM instance forms the result of the delete expression.
Delete the last author of the first book in a given bibliography.
delete node fn:doc("bib.xml")/books/book[1]/author[last()]
Delete all email messages that are more than 365 days old.
delete nodes /email/message [fn:currentDate() - date > xs:dayTimeDuration("P365D")]
Notes:
Since node deletions do not become effective until the end of a snapshot, they have no effect on variable bindings or on the set of available documents or collections within the current query.
The semantics of a delete expression are defined in terms of their effect on an XDM instance: the deleted nodes are detached from their parents after completion of the current query. The effects of a delete expression on persistent storage are beyond the scope of this specification.
[202] | ReplaceExpr |
::= | "replace" ("value" "of")? "node" TargetExpr "with" ExprSingle |
[205] | TargetExpr |
::= | ExprSingle |
A replace expression has two forms, depending on whether value of
is specified.
If value of
is not specified, a replace expression
replaces one node with a new sequence of zero or more nodes. The replacement nodes
occupy the position in the node hierarchy that was formerly occupied by the node that
was replaced. For this reason, an attribute node can be replaced only by zero or more
attribute nodes, and an element, text, comment, or processing instruction node can
be replaced only by zero or more element, text, comment, or processing instruction
nodes.
A replace expression without value of
specified is an updating expression.
The TargetExpr and expression following the keyword with
can be
expressions of any category.
The expression following the keyword with
is evaluated as though it were an enclosed
expression in an element constructor (see Rule 1e in Section
3.9.1.3 Content
XQ30). Let $rlist
be the node sequence that results from this evaluation. If $rlist
contains a document node, the document node is replaced in $rlist
by its children.
TargetExpr is evaluated and checked as follows:
If the result is an empty sequence, [err:XUDY0027] is raised.
If the result is non-empty and does not consist of a single element, attribute, text, comment, or processing instruction node, [err:XUTY0008] is raised.
If the result consists of a node whose parent property is empty, [err:XUDY0009] is raised.
Let
$target
be the node returned by the target expression, and let $parent
be its parent node.
If $target
is an element, text, comment, or processing
instruction node, then $rlist
must consist exclusively of zero or more element, text, comment, or processing instruction
nodes [err:XUTY0010].
If $target
is an attribute node, then:
$rlist
must consist exclusively of zero or more attribute nodes [err:XUTY0011].
No attribute node in $rlist
may have a QName whose implied namespace binding conflicts with a namespace binding in the "namespaces" property of $parent
[err:XUDY0023].
Multiple attribute nodes in $rlist
may not have QNames whose implied namespace bindings conflict with each other [err:XUDY0024].
The result of the replace expression is an empty XDM instance
and a pending update list
constructed
by merging the pending update lists returned
by the TargetExpr and the expression following the keyword with
with the following update primitives
using upd:mergeUpdates:
upd:replaceNode($target, $rlist)
Replace the publisher of the first book with the publisher of the second book.
replace node fn:doc("bib.xml")/books/book[1]/publisher with fn:doc("bib.xml")/books/book[2]/publisher
If value of
is specified,
a replace expression is used to modify the value of a node while preserving
its node identity.
A replace expression with value of
specified is an updating expression.
The TargetExpr and expression following the keyword with
can be
expressions of any category.
The expression following the keyword with
is evaluated as though it were the content
expression of a text node constructor (see Section 3.7.3.4 of
[XQuery 3.0: An XML Query Language].) The result of this step, in the absence of errors, is
either a single text node or an empty sequence. Let $text
be the result of this step.
TargetExpr is evaluated and checked as follows:
If the result is an empty sequence, [err:XUDY0027] is raised.
If the result is non-empty and does not consist of a single element, attribute, text, comment, or processing instruction node, [err:XUTY0008] is raised.
Let
$target
be the node returned by the target expression.
If $target
is an element node, the result of the replace
expression is an empty XDM instance and a
pending update list
constructed
by merging the pending update lists returned
by the TargetExpr and the expression following the keyword with
with the following update primitives
using upd:mergeUpdates:
upd:replaceElementContent($target, $text)
If $target
is an attribute, text, comment, or processing
instruction node, let $string
be the string value of the text node
constructed in Step 1. If Step 1 did not construct
a text node, let $string
be a zero-length string.
Then:
If $target
is a comment node, and $string
contains two adjacent hyphens or ends with a hyphen, a dynamic error is raised [err:XQDY0072].
If $target
is a processing instruction node, and $string
contains the substring "?>
", a dynamic error is raised [err:XQDY0026].
In the absence of errors, the result of a replace expression is an empty
XDM instance and a
pending update list
constructed
by merging the pending update lists returned
by the TargetExpr and the expression following the keyword with
with the following update primitives
using upd:mergeUpdates:
upd:replaceValue($target, $string)
.
Increase the price of the first book by ten percent.
replace value of node fn:doc("bib.xml")/books/book[1]/price with fn:doc("bib.xml")/books/book[1]/price * 1.1
[203] | RenameExpr |
::= | "rename" "node" TargetExpr "as" NewNameExpr |
[205] | TargetExpr |
::= | ExprSingle |
[206] | NewNameExpr |
::= | ExprSingle |
A rename expression replaces the name
property of a data model node with a
new QName.
A rename expression is an updating expression.
The NewNameExpr and TargetExpr can be expressions of any category.
TargetExpr is evaluated and checked as follows:
If the result is an empty sequence, [err:XUDY0027] is raised.
If the result is non-empty and does not consist of a single element, attribute, or processing instruction node, [err:XUTY0012] is raised.
Let
$target
be the node returned by the target expression.
NewNameExpr is processed as follows:
If $target
is an element node, let $QName
be the result of evaluating
NewNameExpr as though it were the name expression of a computed element
constructor (see Section
3.9.3.1 Computed Element Constructors
XQ30). If the namespace binding of $QName
conflicts with any namespace binding in the namespaces
property of $target
, a
dynamic error is raised [err:XUDY0023].
If $target
is an attribute node, let $QName
be the result of evaluating
NewNameExpr as though it were the name expression of a computed attribute
constructor (see Section
3.9.3.2 Computed Attribute
Constructors
XQ30). If $QName
has a non-absent namespace URI, and if the namespace binding of $QName
conflicts with any namespace binding in the namespaces
property of the parent
(if any) of $target
, a dynamic error is raised [err:XUDY0023].
If $target
is a processing instruction node, let $NCName
be the result of
evaluating NewNameExpr as though it were the name expression of a computed
processing instruction constructor (see Section
3.9.3.5 Computed Processing Instruction Constructors
XQ30), and let $QName
be
defined as fn:QName((), $NCName)
.
The result of the rename expression is an empty XDM instance and a pending update list
constructed
by merging the pending update lists returned
by the NewNameExpr and TargetExpr
with the following update primitives
using upd:mergeUpdates:
upd:rename($target, $QName)
.
Rename the first author
element of the first book to principal-author
.
rename node fn:doc("bib.xml")/books/book[1]/author[1] as "principal-author"
Rename the first author
element of the first book to the QName that is the value of the variable $newname
.
rename node fn:doc("bib.xml")/books/book[1]/author[1] as $newname
Note:
The effects of a rename expression are limited to its target node. Attributes and
descendants of the target node are not affected. If a global change of names or namespaces
is intended, some form of explicit iteration must be used. The following example illustrates
such a global change. The example operates on the node bound to variable $root
and all its attributes and descendants, changing all QNames with the prefix abc
to have a new prefix xyz
and a new namespace URI http://xyz/ns
.
for $node in $root//abc:* let $localName := fn:local-name($node), $newQName := fn:concat("xyz:", $localName) return ( rename node $node as fn:QName("http://xyz/ns", $newQName), for $attr in $node/@abc:* let $attrLocalName := fn:local-name($attr), $attrNewQName := fn:concat("xyz:", $attrLocalName) return rename node $attr as fn:QName("http://xyz/ns", $attrNewQName) )
[207] | UpdatingFunctionCall |
::= | "invoke" "updating" PrimaryExpr "(" (ExprSingle ("," ExprSingle)*)? ")" |
A dynamic updating function call dynamically invokes an updating function. A dynamic updating function call is constrained by the grammar so that it cannot be a partial function applicationXQ30.
A dynamic updating function call is an updating expression.
The PrimaryExpr and any argument expressionsXQ30 can be expressions of any category.
A dynamic updating function call is evaluated like a dynamic function invocation, as specified in Section 3.2.2 Dynamic Function Call XQ30. However unlike [7.11 Dynamic Function Invocation] it can invoke either an updating function or a simple function, and could therefore potentially return a non-empty pending update list.
The result of the dynamic updating function call is the XDM instance returned by the function invoked, as well as a pending update list constructed by merging the pending update lists returned by the PrimaryExpr and any argument expressionsXQ30, with the pending update list returned by the function invoked using upd:mergeUpdates.
Dynamically call the fn:put()
function.
let $f := fn:put#2 return invoke updating $f(<newnode/>,"newnode.xml")
[208] | CopyModifyExpr |
::= | "copy" "$" VarName ":=" ExprSingle ("," "$" VarName ":=" ExprSingle)* "modify" ExprSingle "return" ExprSingle |
A copy modify expression can be used to create modified copies of existing nodes in an XDM instance. Each node created by a copy modify expression has a new node identity. The result of a copy modify expression is an XDM instance that may include both nodes that were created by the copy modify expression and other, previously existing nodes.
A copy modify expression consists of three clauses, denoted by the keywords copy
, modify
, and return
.
If all of the copy modify expression's copy
and return
clauses have operand
expressions that are simple expressions,
then the copy modify expression is a simple expression.
If any of the copy modify expression's copy
or return
clauses have operand
expressions that are updating expressions,
then the copy modify expression is a updating expression.
The operand expressions of any of the clauses of a copy modify expression can be expressions of any category.
The copy
clause contains one or more variable bindings, each of which consists of a variable
name and an expression called the source expression. Each variable binding is processed as follows:
The result of evaluating the source expression must be a single node [err:XUTY0013]. Let $node
be this single node.
A new copy is made of $node
and all nodes that have $node
as an ancestor,
collectively referred to as copied nodes. Each copied node receives a new node
identity. The parent
, children
, and attributes
properties of the copied nodes
are set so as to preserve their inter-node relationships.
The parent property of the copy of $node
is set
to empty.
Other properties of the copied nodes are determined as follows:
For a copied document node, the document-uri
property is set to empty.
For a copied element node, the type-name
property is set to xs:untyped
,
and the nilled
, is-id
, and is-idrefs
properties are set to false
.
For a copied attribute node, the type-name
property is set to
xs:untypedAtomic
and the is-idrefs
property is set to false
. The is-id
property
is set to true
if the qualified name of the attribute node is xml:id
; otherwise
it is set to false
.
The string-value
of each copied element and attribute node remains
unchanged, and its typed value becomes equal to its string value as an instance
of xs:untypedAtomic
.
Note:
Implementations that store only the typed value of a node are required at this point to convert the typed value to a string form.
If copy-namespaces mode
in the static context specifies preserve
, all in-scope-namespaces of the original element are
retained in the new copy. If copy-namespaces
mode specifies no-preserve
, the new copy retains only those in-scope namespaces of the original element that
are used in the names of the element and its
attributes.
All other properties of the copied nodes are preserved.
The variable name is bound to the top-level copied node generated in the previous step. The scope of this variable binding includes all subexpressions of the containing copy modify expression that appear after the variable binding clause, including the source expressions of later variable bindings, but it does not include the source expression to which the current variable name is bound.
The expression in the modify
clause is evaluated, resulting in a
pending update list (denoted $pul
)
and an XDM instance. The
XDM instance is discarded, and does not form part
of the result of the copy modify expression.
If the target node of any
update primitive in $pul
is a node that
was not newly created in Step 1, a dynamic error is raised [err:XUDY0014].
If $pul
contains a upd:put
update primitive, a dynamic error is raised
[err:XUDY0037].
Let $revalidation-mode
be the value of
the revalidation mode in the static context of
the library or main module containing
the copy modify expression, and $inherit-namespaces
be the
value of inherit-namespaces in the static context of the copy modify
expression.
The following update operation is invoked: upd:applyUpdates($pul, $revalidation-mode, $inherit-namespaces)
. The effect of this operation is to make the updates specified in the modify
clause effective on the copied nodes.
Note:
In the event of incompatible updates, the upd:applyUpdates operation may raise an error, as described in [8.2.3 upd:applyUpdates].
The return
clause is evaluated, resulting in a
pending update list
and an XDM instance.
The result of the copy modify expression is the
XDM instance returned, as well as a
pending update list constructed by
merging the pending update lists returned
by any of the copy modify expression's copy
or return
clause operand
expressions using upd:mergeUpdates.
During evaluation of the return
clause, changes applied to copied nodes by the preceding
step are visible.
Return a sequence consisting of all employee
elements that have Java as a skill, excluding their salary
child-elements:
for $e in //employee[skill = "Java"] return copy $je := $e modify delete node $je/salary return $je
The following example copies a node, modifies the copy, and returns both the original node and the modified copy:
let $oldx := /a/b/x return copy $newx := $oldx modify (rename node $newx as "newx", replace value of node $newx with $newx * 2) return ($oldx, $newx)
Note:
No persistent changes to the underlying data result from this example.
[97] | TransformWithExpr |
::= | UnaryExpr ( "transform" "with" "{" Expr? "}" )? |
The TransformWithExpr is a convenient short hand for the common
use case of wanting to apply updates to a copy of a single node. If N and U are arbitrary
expressions, and $v
is a variable name that is otherwise unused in U, then the
following TransformWithExpr:
N transform with { U }
is equivalent to the following longer form CopyModifyExpr:
copy $v := N modify $v!(U) return $v
The rules defining compatibility of updating expressions within a snapshot are defined in [8.2.3 upd:applyUpdates].
Note:
The effect of these rules is as follows:
If any node is affected by more than one rename
expression within a snapshot, a dynamic error is raised [err:XUDY0015].
If any node is affected by more than one replace
expression (without value of
being specified) within a snapshot, a dynamic error is raised [err:XUDY0016].
If any node is affected by more than one replace value of
expression within a snapshot, a dynamic error is raised [err:XUDY0017].
If multiple calls to fn:put
operate on the same URI in the same snapshot, a dynamic error is raised [err:XUDY0031].
Within a given snapshot, if an element node E
is the target of a replace value of
expression, and the children of E
are also modified by other expressions, the final children of E
are determined by the replace value of
expression. For example:
Suppose that $A
is bound to an element node that has a child element named B
. Suppose that the following expressions are evaluated in the same snapshot:
replace node $A/B with <C>Hello</C>, replace value of node $A with <D>Goodbye</D>
The expressions on the left and right side of the comma can be evaluated in any order.
No error is raised. At the end of the snapshot, the children of $A
will consist of a single text node with the content "Goodbye"
.