W3C

XQuery Update Facility

W3C Working Draft 11 July 2006

This version:
http://www.w3.org/TR/2006/WD-xqupdate-20060711/
Latest version:
http://www.w3.org/TR/xqupdate/
Previous version:
http://www.w3.org/TR/2006/WD-xqupdate-20060508/
Editors:
Don Chamberlin, IBM Almaden Research Center <chamberlin@almaden.ibm.com>
Daniela Florescu, Oracle Corporation <dana.florescu@oracle.com>
Jonathan Robie, DataDirect Technologies <jonathan.robie@datadirect.com>

Abstract

This document defines an update facility that extends the XML Query language, XQuery. The XQuery Update Facility provides expressions that can be used to make persistent changes to instances of the XQuery 1.0 and XPath 2.0 Data Model.

Status of this Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This document has been produced by the XML Query Working Group (part of the XML Activity), following the procedures set out in the W3C Process Document. It is designed to be read in conjunction with the following documents:

This is a Working Draft published for review by W3C members and other interested parties. Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

Public comments on this document and its open issues are invited. Comments on this document should be made in W3C's public Bugzilla system (instructions can be found at http://www.w3.org/XML/2005/04/qt-bugzilla). When entering comments, select the Product named "XPath / XQuery / XSLT", the Component named "Update Facility", and the Version named "Working drafts". This repository includes open issues recorded by the Query Working Group as well as by members of the public. If access to the Bugzilla system is not feasible, you may send your comments to the W3C XSLT/XPath/XQuery mailing list, public-qt-comments@w3.org. It will be very helpful if you include the string [UPD] in the subject line of your comment, whether made in Bugzilla or in email. Each Bugzilla entry and email message should contain only one comment. Archives of the comments and responses are available at http://lists.w3.org/Archives/Public/public-qt-comments/.

This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

Table of Contents

1 Introduction
2 Extensions to XQuery 1.0
    2.1 Extensions to the Processing Model
    2.2 Extensions to the Prolog
    2.3 New Kinds of Expressions
        2.3.1 Insert
        2.3.2 Delete
        2.3.3 Replace
            2.3.3.1 Replacing a Node
            2.3.3.2 Replacing the Value of a Node
        2.3.4 Rename
        2.3.5 Transform
        2.3.6 Compatibility of Updating Expressions
    2.4 Extensions to Existing Expressions
        2.4.1 FLWOR Expression
        2.4.2 Typeswitch Expression
        2.4.3 Conditional Expression
        2.4.4 Comma Expression
        2.4.5 Parenthesized Expression
        2.4.6 Function Declaration
        2.4.7 Function Call
        2.4.8 Other Expressions
    2.5 Extensions to Built-in Function Library
        2.5.1 fn:put
3 Update Operations
    3.1 Update Primitives
        3.1.1 upd:insertBefore
        3.1.2 upd:insertAfter
        3.1.3 upd:insertInto
        3.1.4 upd:insertIntoAsFirst
        3.1.5 upd:insertIntoAsLast
        3.1.6 upd:insertAttributes
        3.1.7 upd:delete
        3.1.8 upd:replaceNode
        3.1.9 upd:replaceValue
        3.1.10 upd:replaceElementContent
        3.1.11 upd:rename
    3.2 Update Routines
        3.2.1 upd:mergeUpdates
        3.2.2 upd:applyUpdates
        3.2.3 upd:revalidate
        3.2.4 upd:removeType
        3.2.5 upd:setToUntyped

Appendices

A EBNF for XQuery 1.0 Grammar with Update extensions
    A.1 Terminal Symbols
B References
    B.1 Normative References
    B.2 Non-normative References
C Error Conditions
D Glossary (Non-Normative)
E Revision Log (Non-Normative)
    E.1 8 May 2006 Version
    E.2 11 July 2006 Version


1 Introduction

This document defines the syntax and semantics of an extension to [XQuery 1.0] called the XQuery Update Facility. This language extension is designed to meet the requirements for updating instances of the [XQuery/XPath Data Model (XDM)], as defined in [XQuery Update Facility Requirements].

The XQuery Update Facility provides facilities to perform any or all of the following operations on an XDM instance:

[Definition: Within this document, the term XQuery refers to the language specified by [XQuery 1.0].] [Definition: The term data model refers to the data model specified by [XQuery/XPath Data Model (XDM)].] [Definition: The term XDM instance denotes an unconstrained sequence of zero or more nodes and/or atomic values as defined by the data model.]

2 Extensions to XQuery 1.0

The basic building block of XQuery is the expression. XQuery 1.0 provides several kinds of expressions that can be composed with each other in arbitrary ways. An XQuery 1.0 expression takes one or more XDM instances as input and returns an XDM instance as a result. In XQuery 1.0, an expression never modifies the state of an existing node; however, constructor expressions create new nodes with new identities.

XQuery Update Facility introduces a new category of expression called an updating expression, which can potentially modify the state of an existing node.

The extensions to XQuery 1.0 provided by XQuery Update Facility may be characterized as follows:

  1. XQuery Update Facility introduces five new kinds of expressions, called insert, delete, replace, rename, and transform expressions, and specifies the syntax and semantics of each new kind of expression.

  2. XQuery Update Facility classifies XQuery expressions into the following categories:

    1. [Definition: A basic updating expression is an insert, delete, replace, or rename expression, or a call to an updating function.]

    2. [Definition: An updating expression is an expression that contains a basic updating expression that is not inside the modify clause of a transform expression.]

    3. [Definition: A non-updating expression is any XQuery expression that is not an updating expression.]

  3. XQuery Update Facility defines the places where updating and non-updating expressions can be used. In so doing, it makes small extensions to the syntax and semantics of certain existing expressions.

2.1 Extensions to the Processing Model

XQuery Update Facility defines the following extensions to the XQuery processing model:

  1. In XQuery 1.0, the result of each expression is an XDM instance. XQuery Update Facility extends the XQuery processing model so that the result of an expression consists of both an XDM instance and a pending update list (either or both of which may be empty). [Definition: A pending update list is an unordered collection of update primitives, which represent node state changes that have not yet been applied.]

    Note:

    In the current specification, no expression returns both a non-empty XDM instance and a non-empty pending update list.

  2. XQuery Update Facility also defines a set of update operations. [Definition: Update operations are used in defining the semantics of XQuery updates, but are not directly available to users. Update operations are defined in 3 Update Operations.] Update operations fall into the following categories:

    1. [Definition: Update primitives are the components of pending update lists. Each update primitive represents a node state change that has not yet been applied.] [Definition: The first argument of an update primitive, called its target node, is the principal node to be affected by the update primitive.] Update primitives are held on pending update lists until they are made effective by a upd:applyUpdates operation.

    2. [Definition: Update routines are sequences of actions that are used in the definition of XQuery semantics but do not appear on pending update lists.] upd:applyUpdates is an example of an update routine.

  3. If the outermost expression in a query returns a pending update list, upd:applyUpdates is implicitly applied to this pending update list. If this invocation of upd:applyUpdates signals an error condition, a dynamic error is raised [err:TBD].

Note:

[Definition: The upd:applyUpdates operation determines the scope within which all expressions are evaluated before any updates are applied. This is sometimes called the scope of snapshot semantics.] XQuery Update Facility currently calls for upd:applyUpdates to be applied only to the result of the topmost expression in a query, corresponding to query-level snapshot semantics. In principle, upd:applyUpdates could be invoked at a lower level, resulting in expression-level snapshot semantics. This change would require other semantic changes to ensure deterministic results. The Update Language Task Force is currently investigating the issue of snapshot semantics.

2.2 Extensions to the Prolog

[7]    Setter    ::=    BoundarySpaceDecl | DefaultCollationDecl | BaseURIDecl | ConstructionDecl | OrderingModeDecl | EmptyOrderDecl | RevalidationDecl | CopyNamespacesDecl
[141]    RevalidationDecl    ::=    "declare" "revalidation" ("strict" | "lax" | "skip")

The Prolog is extended by adding a new kind of Setter called a revalidation declaration. [Definition: A revalidation declaration sets the revalidation mode in the static context, overriding any implementation-defined default.] If a Prolog contains more than one revalidation declaration, a static error is raised [err:TBD].

[Definition: Revalidation mode, which may be strict, lax, or skip, is a component of the static context that controls the behavior of the upd:revalidate operation.] The value of revalidation mode is determined as follows:

  • Default initial value: strict.

  • Can be overwritten by an implementation: Yes.

  • Can be overwritten by a query: Yes, but a revalidation declaration may not specify a mode that is less strict than the implementation-defined default.

  • Scope: Global.

  • Consistency rules: Must be strict, lax, or skip.

2.3 New Kinds of Expressions

[32]    ExprSingle    ::=    FLWORExpr
| QuantifiedExpr
| TypeswitchExpr
| IfExpr
| InsertExpr
| DeleteExpr
| RenameExpr
| ReplaceExpr
| TransformExpr
| OrExpr

XQuery Update Facility extends the syntax of ExprSingle by adding five new kinds of expressions, called insert, delete, replace, rename, and transform expressions. The syntax and semantics of these expressions are described in the following sections.

2.3.1 Insert

[142]    InsertExpr    ::=    "do" "insert" SourceExpr ((("as" ("first" | "last"))? "into")
| "after"
| "before") TargetExpr
[146]    SourceExpr    ::=    ExprSingle
[147]    TargetExpr    ::=    ExprSingle

An insert expression is an updating expression that inserts copies of one or more nodes into a designated position with respect to a target node, 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 before or after in the same snapshot, the ordering among these nodes is implementation-dependent.

  • If as first (or as last) is specified, the inserted nodes become the first (or last) children of the target node. If multiple nodes are inserted as first (or as last) in the same snapshot, the ordering among these nodes is implementation-dependent.

  • If into is specified without as first or as last, the inserted nodes become children of the target node. Their positions among the children of the target node are implementation-dependent but do not conflict with the positions of nodes inserted before, after, as first, or as last in the same snapshot.

Examples:

  • Insert a year element after the publisher of the first book.

    do insert <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.

    do insert $new-police-report
       as last into fn:doc("insurance.xml")/policies
          /policy[id = $pid]
          /driver[license = $license]
          /accident[date = $accdate]
          /police-reports
    

The semantics of an insert expression are as follows:

  1. SourceExpr must not be an updating expression; otherwise a static error is raised [err:XUST0001]. SourceExpr is evaluated as though it were an enclosed expression in an element constructor (see Rule 1e in Section 3.7.1.3 of [XQuery 1.0]). 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:TBD]. 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.

  2. The target expression must not be an updating expression; otherwise a static error is raised [err:XUST0001]. The target expression is evaluated. If into is specified, the result must be a single element node or a single document node; otherwise a type error is raised [err:TBD]. If before or after is specified, the result must be a single element node whose parent property is not empty; otherwise a dynamic error is raised [err:TBD]. Let $target be the node returned by the target expression.

  3. The result of the insert expression is an empty XDM instance and a pending update list constructed as follows:

    1. If as first is specified, the pending update list consists of the following update primitives:

      1. If $alist is not empty, upd:insertAttributes($target, $alist)

      2. If $clist is not empty, upd:insertIntoAsFirst($target, $clist)

    2. If as last is specified, the pending update list consists of the following update primitives:

      1. If $alist is not empty, upd:insertAttributes($target, $alist)

      2. If $clist is not empty, upd:insertIntoAsLast($target, $clist)

    3. If into is specified and neither as first nor as last is specified, the pending update list consists of the following update primitives:

      1. If $alist is not empty, upd:insertAttributes($target, $alist)

      2. If $clist is not empty, upd:insertInto($target, $clist)

    4. If before is specified, let $parent be the parent node of $target. The pending update list consists of the following update primitives:

      1. If $alist is not empty, upd:insertAttributes($parent, $alist)

      2. If $clist is not empty, upd:insertBefore($target, $clist)

    5. If after is specified, let $parent be the parent node of $target. The pending update list consists of the following update primitives:

      1. If $alist is not empty, upd:insertAttributes($parent, $alist)

      2. If $clist is not empty, upd:insertAfter($target, $clist)

2.3.2 Delete

[143]    DeleteExpr    ::=    "do" "delete" TargetExpr
[147]    TargetExpr    ::=    ExprSingle

A delete expression deletes zero or more nodes from an XDM instance. A delete expression is an updating expression.

Examples:

  • Delete the last author of the first book in a given bibliography.

    do delete fn:doc("bib.xml")/books/book[1]/author[last()]
    
  • Delete all email messages that are more than 365 days old.

    do delete /email/message
         [fn:currentDate() - date > xs:dayTimeDuration("P365D")]
    

The semantics of a delete expression are as follows:

  1. The target expression must not be an updating expression; otherwise a static error is raised [err:XUST0001]. The target expression is evaluated. The result must be a sequence of zero or more nodes; otherwise a type error is raised [err:TBD]. Let $tlist be the list of nodes returned by the target expression.

  2. 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 (together with an empty XDM instance) is the result of the delete expression.

2.3.3 Replace

[144]    ReplaceExpr    ::=    "do" "replace" ("value" "of")? TargetExpr "with" ExprSingle
[147]    TargetExpr    ::=    ExprSingle

A replace expression is an updating expression. A replace expression has two forms, depending on whether value of is specified.

2.3.3.1 Replacing a Node

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. Example:

  • Replace the publisher of the first book with the publisher of the second book.

    do replace fn:doc("bib.xml")/books/book[1]/publisher
    with fn:doc("bib.xml")/books/book[2]/publisher
    

The semantics of this form of replace expression are as follows:

  1. The expression following the keyword with must not be an updating expression; otherwise a static error is raised [err:XUST0001]. This expression is evaluated as though it were an enclosed expression in an element constructor (see Rule 1e in Section 3.7.1.3 of [XQuery 1.0]). 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.

  2. The target expression must not be an updating expression; otherwise a static error is raised [err:XUST0001]. The target expression is evaluated. The result must be a single node whose parent property is not empty; otherwise a dynamic error is raised [err:TBD]. Let $target be the node returned by the target expression, and let $parent be its parent node.

    Note:

    $target may not be a document node, since a document node does not have a parent property.

  3. 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:TBD]. If $target is an attribute node, then $rlist must consist exclusively of zero or more attribute nodes [err:TBD].

  4. The result of the replace expression is an empty XDM instance and a pending update list consisting of the following update primitive: upd:replaceNode($target, $rlist)

2.3.3.2 Replacing the Value of a Node

If value of is specified, a replace expression is used to modify the value of a node while preserving its node identity. Example:

  • Increase the price of the first book by ten percent.

    do replace value of fn:doc("bib.xml")/books/book[1]/price
    with fn:doc("bib.xml")/books/book[1]/price * 1.1
    

The semantics of this form of replace expression are as follows:

  1. The expression following the keyword with must not be an updating expression; otherwise a static error is raised [err:XUST0001]. This expression is evaluated as though it were the content expression of a text node constructor (see Section 3.7.3.4 of [XQuery 1.0].) The result of this step is either an error or a single text node. Let $text be the text node resulting from this step.

  2. The target expression must not be an updating expression; otherwise a static error is raised [err:XUST0001]. The target expression is evaluated. The result must be a single node; otherwise a type error is raised [err:TBD]. Let $target be the node returned by the target expression.

  3. If $target is an element node, the result of the replace expression is an empty XDM instance and a pending update list consisting of the following update primitive: upd:replaceElementContent($target, $text)

  4. 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. The result of the replace expression is an empty XDM instance and a pending update list containing the following update primitive: upd:replaceValue($target, $string).

  5. If $target is a document node, a type error is raised [err:TBD].

2.3.4 Rename

[145]    RenameExpr    ::=    "do" "rename" TargetExpr "as" NewNameExpr
[147]    TargetExpr    ::=    ExprSingle
[148]    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.

Examples:

  • Rename the first author element of the first book to principal-author.

    do rename 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.

    do rename fn:doc("bib.xml")/books/book[1]/author[1]
    as $newname
    

The semantics of a rename expression are as follows:

  1. The target expression must not be an updating expression; otherwise a static error is raised [err:XUST0001]. The target expression is evaluated. The result must be a single element, attribute, or processing instruction node; otherwise a type error is raised [err:TBD]. Let $target be the node returned by the target expression.

  2. NewNameExpr must not be an updating expression; otherwise a static error is raised [err:XUST0001]. NewNameExpr is evaluated as though it were the name expression of a computed element constructor (see Section 3.7.3.1 of [XQuery 1.0].) The result is either an error or an expanded QName. Let $QName be this expanded QName.

  3. The result of the rename expression is an empty XDM instance and a pending update list containing the following update primitive: upd:rename($target, $QName).

2.3.5 Transform

[149]    TransformExpr    ::=    "transform" "copy" "$" VarName ":=" ExprSingle ("," "$" VarName ":=" ExprSingle)* "modify" ExprSingle "return" ExprSingle

A transform expression can be used to create modified copies of existing nodes in an XDM instance. Each node created by a transform expression has a new node identity. The result of a transform expression is an XDM instance that may include both nodes that were created by the transform expression and other, previously existing nodes. A transform expression is a non-updating expression because it does not modify the value of any existing nodes.

Example:

  • 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
       transform 
          copy $je := $e
          modify do delete $je/salary
          return $je
    

A transform expression consists of three clauses, denoted by the keywords copy, modify, and return. The semantics of a transform expression are as follows:

  1. 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:

    1. The source expression must not be an updating expression; otherwise a static error is raised [err:XUST0001]. The source expression is evaluated as though it were an enclosed expression in an element constructor (see Rule 1e in Section 3.7.1.3 of [XQuery 1.0].) The result of this step is either an error or a sequence of nodes called the copied node sequence.

      Note:

      Each node in the copied node sequence is a newly created node with a new nodeid.

    2. The variable name is bound to the copied node sequence. The scope of this variable binding includes all subexpressions of the containing transform 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.

  2. The modify clause must contain either an updating expression, an empty expression ( ), or a call to the fn:error function; otherwise a static error is raised [err:XUST0002]. The expression in the modify clause is evaluated, resulting in a pending update list. If the target node of any update primitive on this pending update list is a node that was not newly created in Step 1, a dynamic error is raised [err:TBD]. Let $pul be the pending update list generated by this step.

  3. The following update operation is invoked: upd:applyUpdates($pul). The effect of this operation is to make the updates specified in the modify clause effective on the nodes in the copied node lists.

  4. The return clause must not contain an updating expression; otherwise a static error is raised [err:XUST0001]. The return clause is evaluated, and its result is the result of the transform expression. During evaluation of the return clause, changes applied to copied nodes by the preceding step are visible.

2.3.6 Compatibility of Updating Expressions

The following rules are enforced during the processing of updating expressions:

  1. A given node may not be the target of more than one rename expression within a given snapshot [err:TBD].

  2. A given node may not be the target of more than one replace expression (without value of being specified) within a given snapshot [err:TBD].

  3. A given node may not be the target of more than one replace value of expression within a given snapshot [err:TBD].

  4. 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:

      do replace $A/B with <C>Hello</C>,
      do replace value of $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".

2.4 Extensions to Existing Expressions

XQuery Update Facility provides extensions to the semantics of several existing kinds of XQuery expressions, as specified in this section.

2.4.1 FLWOR Expression

The syntax of the FLWOR expression is not changed. Its semantics are extended as follows:

  1. If a for, let, where, or order by clause contains an updating expression, a static error is raised [err:XUST0001].

  2. If the return clause contains a non-updating expression, the FLWOR expression is a non-updating expression, and its semantics are as specified in Section 3.8 of [XQuery 1.0].

  3. If the return clause contains an updating expression, the FLWOR expression is an updating expression, and its semantics are as follows:

    1. The semantics of the for, let, where, and order by clauses are as specified in Section 3.8 of [XQuery 1.0]. These clauses generate a stream of tuples of bound variables.

    2. For each tuple generated by the previous step, the updating expression in the return clause is evaluated, resulting in a pending update list.

    3. All the pending update lists generated by the previous step are merged by successive invocations of the upd:mergeUpdates operation. If the upd:mergeUpdates operation signals an incompatibility, a dynamic error is raised [err:TBD]. Otherwise, the result of the FLWOR expression is the merged pending update list returned by the final upd:mergeUpdates operation.

The following example illustrates the use of an updating expression in a FLWOR expression:

  • Update an inventory of parts according to a set of changes provided in the bound variable $changes. Both /inventory and $changes contain a set of part elements, each with a partno and a quantity.

    for $p in /inventory/part
    let $deltap := $changes/part[partno eq $p/partno]
    return do replace value of $p/quantity
          with $p/quantity + $deltap/quantity
    

2.4.2 Typeswitch Expression

[43]    TypeswitchExpr    ::=    "typeswitch" "(" Expr ")" CaseClause+ "default" ("$" VarName)? "return" ExprSingle
[44]    CaseClause    ::=    "case" ("$" VarName "as")? SequenceType "return" ExprSingle

The syntax of the typeswitch expression is unchanged. Its semantics are extended as follows (the term "branch" refers to any case or default clause in the typeswitch expression):

  1. If the operand expression of a typeswitch is an updating expression, a static error is raised [err:XUST0001].

  2. If any branch contains an updating expression, the typeswitch expression is an updating expression; otherwise it is a non-updating expression.

  3. If the typeswitch expression is a non-updating expression, its semantics are as specified in Section 3.12.2 of [XQuery 1.0].

  4. If the typeswitch expression is an updating expression, then all of its branches must contain either an updating expression, an empty expression ( ), or a call to the fn:error function; otherwise a static error is raised [err:XUST0001]. In this case, selection of the effective case and binding of variables is performed as specified in Section 3.12.2 of [XQuery 1.0]. The expression in the return clause of the effective case (or default) is then evaluated, resulting in a pending update list, which serves as the result of the typeswitch expression.

2.4.3 Conditional Expression

The semantics of conditional expressions are extended as follows (the term "branch" refers to the then and else clauses in the conditional expression):

  1. If any branch contains an updating expression, the conditional expression is an updating expression; otherwise it is a non-updating expression.

  2. If the conditional expression is a non-updating expression, its semantics are as specified in Section 3.10 of [XQuery 1.0].

  3. If the conditional expression is an updating expression, then both of its branches must contain either an updating expression, an empty expression ( ), or a call to the fn:error function; otherwise a static error is raised [err:XUST0001]. In this case, the test expression is evaluated and the then or else clause is selected and evaluated as specified in Section 3.10 of [XQuery 1.0]. The result of the conditional expression is the pending update list returned by the selected branch.

The following example illustrates the use of updating expressions in a conditional expression:

  • If the element bound to variable $e has a last-updated attribute, update its value to the current date; otherwise insert such an attribute.

    if ($e/@last-updated)
    then do replace value of $e/last-updated with fn:currentDate()
    else do insert attribute last-updated {fn:currentDate()} into $e
    

2.4.4 Comma Expression

The semantics of comma expressions (composed of one or more expressions concatenated by the comma operator, as described in Section 3.3.1 of [XQuery 1.0]) are extended as follows:

  1. If any operand of the comma expression is an updating expression, the comma expression is an updating expression; otherwise it is a non-updating expression.

  2. If the comma expression is a non-updating expression, its semantics are as specified in Section 3.3.1 of [XQuery 1.0].

  3. If the comma expression is an updating expression, then each of its operands must be either an updating expression, an empty expression ( ), or a call to the fn:error function; otherwise a static error is raised [err:XUST0001]. In this case, the operand expressions are evaluated (in any order), and the pending update lists returned by the operand expressions are merged by the upd:mergeUpdates operation. The resulting merged pending update list is the result of the comma expression.

The following example illustrates the use of an updating comma expression:

  • This example makes the value of an element empty and gives the element an xsi:nil="true" attribute. Both of these operations may be necessary in order to preserve the validity of the element.

    let $q := /inventory/item[serialno = "123456"]/quantity
    return
       do replace value of $q with ( ),
       do insert attribute xsi:nil {"true"} into $q
    

2.4.5 Parenthesized Expression

The semantics of a parenthesized expression (any XQuery expression enclosed in parentheses) are extended as follows:

The category of a parenthesized expression is the same as the category of its operand expression, which may be an updating expression or a non-updating expression. The result of a parenthesized expression is also the same as the result of its operand expression. An empty parenthesized expression ( ) is a non-updating expression, and its result is an empty sequence.

2.4.6 Function Declaration

[26]    FunctionDecl    ::=    "declare" "updating"? "function" QName "(" ParamList? ")" ("as" SequenceType)? (EnclosedExpr | "external")

The syntax of a function declaration is extended to include an optional keyword: updating. The semantics of a function declaration, described in Section 4.15 of [XQuery 1.0], are extended as follows:

  1. If updating is not specified:

    1. If external is not specified, the EnclosedExpr in the function declaration must be a non-updating expression; otherwise a static error is raised [err:XUST0001].

    2. If external is specified, the external function must not return a non-empty pending update list; otherwise a dynamic error is raised [err:TBD].

  2. If updating is specified:

    1. as SequenceType must not be specified because, in the current design, the XDM instance returned by an updating expression is always the empty sequence.

    2. If external is not specified, the EnclosedExpr in the function declaration must be an updating expression, an empty expression ( ), or a call to the fn:error function; otherwise a static error is raised [err:XUST0002].

    3. If external is specified, the external function may return a non-empty pending update list but it must not return a non-empty XDM instance; otherwise a dynamic error is raised [err:TBD].

The means by which an external function returns an XDM instance or a pending update list is implementation-defined.

The following example illustrates a declaration of an updating function.

  • This function takes an element, a QName, and an atomic value. If the given element has an attribute with the given QName, the function updates the attribute with the given value; otherwise it inserts a new attribute with the given name and value.

    declare updating function 
       upsert($e as element(), 
              $an as xs:QName, 
              $av as xs:anyAtomicType) 
       {
       let $ea := $e/attribute()[fn:node-name(.) = $an]
       return
          if (fn:empty($ea))
          then do insert attribute {$an} {$av} into $e
          else do replace value of $ea with $av
       }
    

2.4.7 Function Call

The semantics of a function call are extended as follows:

The function call is evaluated as specified in Section 3.1.5 of [XQuery 1.0]. If any input parameter of the function call is an updating expression, a static error is raised [err:XUST0001]. If the called function was declared with the updating keyword, the function call is an updating expression. If the called function was declared without the updating keyword, the function call is a non-updating expression.

2.4.8 Other Expressions

The semantics of all XQuery expressions other than FLWOR expressions, typeswitch expressions, conditional expressions, comma expressions, parenthesized expressions, and function calls are extended as follows:

If any operand of this expression is an updating expression, a static error is raised [err:XUST0001].

2.5 Extensions to Built-in Function Library

XQuery Update Facility provides extensions to XQuery built-in function library, as specified in this section.

2.5.1 fn:put

fn:put($node as node())
fn:put($node as node(), $uri as xs:string?)

Summary: Stores a document or element to the location specified by an xs:anyURI. This function is normally invoked to create a resource on an external storage system such as a file system or a database.

Since snapshot semantics are always preserved by updates, this function has no effect on the query currently being executed.

If $node is not a document node or an element node, an error is raised [err:TBD]. If fn:put is called more than once with the same URI in one query, an error is raised [err:TBD]. If $uri is not a valid xs:anyURI, an error is raised [err:TBD]. If $uri is the empty sequence, an error is raised [err:TBD].

If $uri is a relative URI Reference, it is resolved relative to the value of the base URI property from the static context, and the resulting absolute URI Reference is promoted to an xs:string. If $uri is not specified, the document URI of $node is used; this is equivalent to fn:put ($node, fn:document-uri($node)).

The results of this function are implementation-defined, since they occur completely outside the domain of XQuery. In most environments, if fn:put did not report an error, a subsequent query can access the stored document by invoking fn:doc with the same URI. In most implementations, this function adds implementation-defined updates to the Pending Update List.

The set of URI schemes that the implementation recognizes is implementation-defined. Implementations may allow the mapping of URIs to resources to be configured by the user, using mechanisms such as catalogs or user-written URI handlers.

Preservation of type information is implementation defined; an implementation may store either the Data Model representation of $node or the Infoset Mapping of $node.

Mapping to non-XML media types is implementation-defined. Implementations may allow instances of the data model to be stored as non-XML resources, under user control.

Implementations may provide user-defined error handling options that allow processing to continue following an error in storing a resource.

3 Update Operations

This section describes the update operations defined by XQuery Update Facility. Although these update operations are described using a functional notation, they are not true functions because many of them have no return value. These update operations are used in defining the semantics of XQuery expressions, but they are not directly available to users.

Update operations consist of update primitives, which are the components of pending update lists, and update routines, which are used in defining XQuery semantics but do not appear on pending update lists.

The definitions of some update operations utilize the concept of marking a node. [Definition: To mark a node means to identify the node as participating in a later operation.] Marking of nodes is accomplished in an implementation-dependent way--for example, an implementation might maintain a list of marked nodes. Two kinds of marks are used in update operations, and their respective nodes are said to be marked for deletion or marked for revalidation.

3.1 Update Primitives

The update primitives described in this section may be held on pending update lists. When an update primitive is held on a pending update list, its node operands are represented by nodeids. The semantics of an update primitive do not become effective until their pending update list is processed by the upd:applyUpdates routine.

3.1.1 upd:insertBefore

Parameters
upd:insertBefore(
   $target as node(),
   $content as node()+)
Summary

Inserts $content immediately before $target.

Constraints

$target must be an element, text, processing instruction, or comment node with a non-empty parent property. $content must be a sequence containing only element, text, processing instruction, and comment nodes.

Semantics
  1. Effects on nodes in $content:

    1. For each node in $content, the parent property is set to parent($target).

    2. If the type-name property of parent($target) is xs:untyped, then upd:setToUntyped() is invoked on each element or attribute node in $content.

  2. Effects on parent($target):

    1. The children property of parent($target) is modified to add the nodes in $content just before $target, preserving their order.

    2. If at least one of the nodes in $content is an element or text node, upd:removeType(parent($target)) is invoked.

3.1.2 upd:insertAfter

Parameters
upd:insertAfter(
   $target as node(),
   $content as node()+)
Summary

Inserts $content immediately after $target.

Constraints

$target must be an element, text, processing instruction, or comment node with a non-empty parent property. $content must be a sequence containing only element, text, processing instruction, and comment nodes.

Semantics

The semantics of upd:insertAfter are identical to the semantics of upd:insertBefore, except that Rule 2a is changed as follows:

  • The children property of parent($target) is modified to add the nodes in $content just after $target, preserving their order.

3.1.3 upd:insertInto

Parameters
upd:insertInto(
   $target as node(),
   $content as node()+)
Summary

Inserts $content as the children of $target, in an implementation-defined position.

Constraints

$target must be an element or document node. $content must be a sequence containing only element, text, processing instruction, and comment nodes.

Semantics

The semantics of upd:insertInto are identical to the semantics of upd:insertBefore, except that $target is substuted everywhere for parent($target), and Rule 2a is changed as follows:

  • The children property of $target is changed to include the nodes in $content. The order among the new children, and their position within the parent node, is implementation-dependent.

3.1.4 upd:insertIntoAsFirst

Parameters
upd:insertIntoAsFirst(
   $target as node(),
   $content as node()+)
Summary

Inserts $content as the first children of $target.

Constraints

$target must be an element or document node. $content must be a sequence containing only element, text, processing instruction, and comment nodes.

Semantics

The semantics of upd:insertIntoAsFirst are identical to the semantics of upd:insertBefore, except that $target is substuted everywhere for parent($target), and Rule 2a is changed as follows:

  • The children property of $target is changed to include the nodes in $content as the first children, preserving their order.

3.1.5 upd:insertIntoAsLast

Parameters
upd:insertIntoAsLast(
   $target as node(),
   $content as node()+)
Summary

Inserts $content as the last children of $target.

Constraints

$target must be an element or document node. $content must be a sequence containing only element, text, processing instruction, and comment nodes.

Semantics

The semantics of upd:insertIntoAsLast are identical to the semantics of upd:insertBefore, except that $target is substuted everywhere for parent($target), and Rule 2a is changed as follows:

  • The children property of $target is changed to include the nodes in $content as the last children, preserving their order.

3.1.6 upd:insertAttributes

Parameters
upd:insertAttributes(
   $target as element(),
   $content as attribute()+)
Summary

Inserts $content as attributes of $target.

Constraints

None

Semantics
  1. For each node $A in $content:

    1. The parent property of $A is set to $target.

    2. If the type-name property of $target is xs:untyped, then upd:setToUntyped($A) is invoked.

  2. The following properties of $target are changed:

    1. attributes: Modified to include the nodes in $content.

    2. namespaces: Modified to include namespace bindings for any attribute namespace prefixes in $content that did not already have bindings.

    3. upd:removeType($target) is invoked.

3.1.7 upd:delete

Parameters
upd:delete(
   $target as node())
Constraints

None

Semantics

$target is marked for deletion.

3.1.8 upd:replaceNode

Parameters
upd:replaceNode(
   $target as node(),
   $replacement as node()*)
Summary

Replaces $target with $replacement.

Constraints

$target must be a node that has a parent. If $target is an attribute node, $replacement must consist of zero or more attribute nodes. If $target is an element, text, comment, or processing instruction node, $replacement must be consist of zero or more element, text, comment, or processing instruction nodes.

Semantics
  1. Effects on nodes in $replacement:

    1. For each node in $replacement, the parent property is set to parent($target).

    2. If the type-name property of parent($target) is xs:untyped, then upd:setToUntyped() is invoked on each element node in $replacement.

  2. Effect on $target:

    1. $target is marked for deletion.

  3. Effects on parent($target):

    1. If $target is an attribute node, the attributes property of parent($target) is replaced by $replacement.

    2. If $target is an element, text, comment, or processing instruction node, the children property of parent($target) is modified to add the nodes in $replacement just before $target, preserving their order.

    3. upd:removeType(parent($target)) is invoked.

3.1.9 upd:replaceValue

Parameters
upd:replaceValue(
   $target as node(),
   $string-value as xs:string)
Summary

Replaces the string value of $target with $string-value.

Constraints

$target must be an attribute, text, comment, or processing instruction node.

Semantics
  1. If $target is an attribute node:

    1. string-value of $target is set to $string-value.

    2. upd:removeType($target) is invoked.

  2. If $target is a text, comment, or processing instruction node: content of $target is set to $string-value.

  3. If $target is a text node, upd:removeType(parent($target)) is invoked.

3.1.10 upd:replaceElementContent

Parameters
upd:replaceElementContent(
   $target as element(),
   $text as text()?)
Summary

Replaces the existing children of the element node $target by the optional text node $text. The attributes of $target are not affected.

Constraints

None.

Semantics
  1. For each node $C that is a child of $target, the parent property of $C is set to empty.

  2. The parent property of $text is set to $target.

  3. Effects on $target:

    1. children is set to consist exclusively of $text. If $text is an empty sequence, then $target has no children.

    2. typed-value and string-value are set to the content property of $text. If $text is an empty sequence, then typed-value is an empty sequence and string-value is an empty string.

    3. upd:removeType($target) is invoked.

3.1.11 upd:rename

Parameters
upd:rename(
   $target as node(),
   $newName as xs:QName)
Summary

Changes the node-name of $target to $newName.

Constraints

$target must be an element, attribute, or processing instruction node.

Semantics
  1. If $target is an element node:

    1. node-name of $target is set to $newName.

    2. upd:removeType($target) is invoked.

  2. If $target is an attribute node:

    1. node-name of $target is set to $newName.

    2. upd:removeType($target) is invoked.

    3. If $newName is xml:id, the is-id property of $target is set to true.

    4. The namespaces property of parent($target) is modified to include a namespace binding derived from $newName, if this binding did not already exist.

  3. If $target is a processing instruction node, its target property is set to $newName.

3.2 Update Routines

3.2.1 upd:mergeUpdates

Parameters
upd:mergeUpdates(
   $pul1 as pending-update-list,
   $pul2 as pending-update-list)
Summary

Merges two pending update lists.

Constraints

None.

Semantics
  1. The two pending update lists are merged and a single pending update list containing all the update primitives from both lists is returned.

  2. Optionally, an implementation may signal an incompatibility if any of the following conditions are detected:

    1. Two or more upd:replaceNode primitives on the merged list have the same target node.

    2. Two or more upd:replaceValue primitives on the merged list have the same target node.

    3. Two or more upd:rename primitives on the merged list have the same target node.

3.2.2 upd:applyUpdates

Parameters
upd:applyUpdates(
   $pul as pending-update-list)
Constraints

None.

Summary

This routine is used at the end of a snapshot to make effective the semantics of all the update primitives on a pending update list and to revalidate the resulting XDM instance.

Semantics
  1. Checks the update primitives on $pul for compatibility. Signals an incompatability if any of the following conditions are detected:

    1. Two or more upd:replaceNode primitives on $pul have the same target node.

    2. Two or more upd:replaceValue primitives on $pul have the same target node.

    3. Two or more upd:replaceElementContent primitives on $pul have the same target node.

    4. Two or more upd:rename primitives on $pul have the same target node.

  2. The semantics of all the update primitives on $pul are made effective, in the following order:

    1. First, all upd:insertInto, upd:insertAttributes, upd:replaceValue, upd:rename, and upd:delete primitives are applied.

      Note:

      As a result of applying these primitives, some nodes may be marked for deletion, but will not be physically deleted until a later step.

    2. Next, all upd:insertBefore, upd:insertAfter, upd:insertIntoAsFirst, and upd:insertIntoAsLast primitives are applied.

    3. Next, all upd:replaceNode primitives are applied.

    4. Next, all upd:replaceElementContent primitives are applied.

    5. Finally, for each node marked for deletion by one of the update primitives listed above, let $N be the node that is marked for deletion, and let $P be its parent node. The following actions are applied:

      1. The parent property of $N is set to empty.

      2. If $N is an attribute node, the attributes property of $P is modified to remove $N.

      3. If $N is a non-attribute node, the children property of $P is modified to remove $N.

      4. If $N is an element, attribute, or text node, and $P is an element node, then upd:removeType($P) is invoked.

    Note:

    The effects of node deletions on variable bindings and on available documents and collections are under discussion.

  3. If, as a net result of the above steps, the children property of some node contains adjacent text nodes, these adjacent text nodes are merged into a single text node. The string-value of the resulting text node is the concatenated string-values of the adjacent text nodes, with no intervening space added. The nodeid of the resulting text node is implementation-dependent.

  4. For each document or element node $top that was marked for revalidation by one of the earlier steps, upd:revalidate($top) is invoked.

  5. If the resulting XDM instance violates any consistency constraint specified in [XQuery/XPath Data Model (XDM)], an error is signaled [err:TBD].

  6. The upd:applyUpdates operation is atomic with respect to the data model. In other words, if upd:applyUpdates terminates normally, the resulting XDM instance reflects the result of all update primitives; but if upd:applyUpdates raises an error, the resulting XDM instance reflects no changes. Propagation of XDM changes to an underlying physical representation is beyond the scope of this specification.

3.2.3 upd:revalidate

Parameters
upd:revalidate(
   $top as node())
Constraints

$top must be a document node or an element node.

Summary

Schema validation is applied to the subtree rooted at $top in order to recover the types of updated nodes while preserving their nodeids.

Semantics

If revalidation mode in the static context is skip, upd:revalidate performs no action. Otherwise:

  1. If revalidation mode in the static context is lax, define $topV as the result of the XQuery expression validate lax {$top}. If revalidation mode is strict, define $topV as the result of the XQuery expression validate strict {$top}. During computation of $topV, it is necessary to maintain a mapping between each node in $topV and the corresponding node (if any) in the subtree rooted at $top (this mapping is maintained in an implementation-dependent way.)

    Note:

    This step may raise an error if $top is found to be invalid.

    Note:

    Some of the nodes in $topV (for example, default attributes generated by the validation process) may have no corresponding nodes in $top.

  2. For each node $nV in $topV that has a corresponding node $n in $top, replace the following properties of $n with the corresponding properties of $nV: type-name, typed-value, string-value, is-id, is-idrefs, namespace-bindings, nilled.

  3. For each node $nV in $topV that does not have a corresponding node in $top, insert the node $nV into the subtree rooted at $top as a child or attribute of the node corresponding to the parent of $nV.

  4. The result of upd:revalidate is to modify the properties of the nodes rooted at $top and possibly to add some new nodes to this subtree. When the revalidation process is complete, $topV can be discarded.

Note:

After revalidation, the type annotations of the nodes in the validated subtree are consistent with their content. It is expected that implementations will optimize the revalidation process by taking into account which nodes have been modified since they were last validated.

3.2.4 upd:removeType

Parameters
upd:removeType(
   $N as node())
Constraints

$N must be an element or attribute node

Summary

This routine is applied to a node whose name or content has been modified, in order to remove specific type information from the node and its ancestors, pending revalidation.

Semantics
  1. If $N is an element node, its properties are changed as follows:

    1. If type-name is not equal to xs:untyped, then

      1. type-name is set to xs:anyType

      2. If the parent of N is an element node, then upd:removeType(parent($N)) is invoked.

    2. string-value is set equal to the concatenated contents of the text node descendants, in document order.

    3. typed-value is set equal to the string-value property, as an instance of xs:untypedAtomic.

      Note:

      The data model allows some flexibility to implementations regarding whether string-value and/or typed-value are stored or computed dynamically.

    4. nilled, is-id, and is-idrefs are set to false.

  2. If $N is an attribute node, its properties are changed as follows:

    1. type-name is set to xs:untypedAtomic.

    2. typed-value is set equal to the string-value property, as an instance of xs:untypedAtomic.

    3. is-id and is-idrefs are set to false.

    4. If $N has a parent, upd:removeType(parent($N)) is invoked.

  3. The topmost ancestor of $N is marked for revalidation.

3.2.5 upd:setToUntyped

Parameters
upd:setToUntyped(
   $N as node())
Constraints

$N must be an element or attribute node

Summary

This routine is applied to a node that has been inserted into an untyped context, which requires that the node and its descendants be untyped as well.

Semantics
  1. If $N is an element node, its properties are changed as follows:

    1. type-name is set to xs:untyped.

    2. typed-value is set equal to the string-value property, as an instance of xs:untypedAtomic.

      Note:

      The data model allows some flexibility to implementations regarding whether string-value and/or typed-value are stored or computed dynamically.

    3. nilled, is-id, and is-idrefs are set to false.

    4. upd:setToUntyped() is invoked on the attributes and child element nodes of $N.

  2. If $N is an attribute node, its properties are changed as follows:

    1. type-name is set to xs:untypedAtomic.

    2. typed-value is set equal to the string-value property, as an instance of xs:untypedAtomic.

    3. is-id and is-idrefs are set to false.

A EBNF for XQuery 1.0 Grammar with Update extensions

The EBNF in this document and in this section is aligned with the current XML Query 1.0 grammar (see [XQuery 1.0]).

[1]    Module    ::=    VersionDecl? (LibraryModule | MainModule)
[2]    VersionDecl    ::=    "xquery" "version" StringLiteral ("encoding" StringLiteral)? Separator
[3]    MainModule    ::=    Prolog QueryBody
[4]    LibraryModule    ::=    ModuleDecl Prolog
[5]    ModuleDecl    ::=    "module" "namespace" NCName "=" URILiteral Separator
[6]    Prolog    ::=    ((DefaultNamespaceDecl | Setter | NamespaceDecl | Import) Separator)* ((VarDecl | FunctionDecl | OptionDecl) Separator)*
[7]    Setter    ::=    BoundarySpaceDecl | DefaultCollationDecl | BaseURIDecl | ConstructionDecl | OrderingModeDecl | EmptyOrderDecl | RevalidationDecl | CopyNamespacesDecl
[8]    Import    ::=    SchemaImport | ModuleImport
[9]    Separator    ::=    ";"
[10]    NamespaceDecl    ::=    "declare" "namespace" NCName "=" URILiteral
[11]    BoundarySpaceDecl    ::=    "declare" "boundary-space" ("preserve" | "strip")
[12]    DefaultNamespaceDecl    ::=    "declare" "default" ("element" | "function") "namespace" URILiteral
[13]    OptionDecl    ::=    "declare" "option" QName StringLiteral
[14]    OrderingModeDecl    ::=    "declare" "ordering" ("ordered" | "unordered")
[15]    EmptyOrderDecl    ::=    "declare" "default" "order" "empty" ("greatest" | "least")
[16]    CopyNamespacesDecl    ::=    "declare" "copy-namespaces" PreserveMode "," InheritMode
[17]    PreserveMode    ::=    "preserve" | "no-preserve"
[18]    InheritMode    ::=    "inherit" | "no-inherit"
[19]    DefaultCollationDecl    ::=    "declare" "default" "collation" URILiteral
[20]    BaseURIDecl    ::=    "declare" "base-uri" URILiteral
[21]    SchemaImport    ::=    "import" "schema" SchemaPrefix? URILiteral ("at" URILiteral ("," URILiteral)*)?
[22]    SchemaPrefix    ::=    ("namespace" NCName "=") | ("default" "element" "namespace")
[23]    ModuleImport    ::=    "import" "module" ("namespace" NCName "=")? URILiteral ("at" URILiteral ("," URILiteral)*)?
[24]    VarDecl    ::=    "declare" "variable" "$" QName TypeDeclaration? ((":=" ExprSingle) | "external")
[25]    ConstructionDecl    ::=    "declare" "construction" ("strip" | "preserve")
[26]    FunctionDecl    ::=    "declare" "updating"? "function" QName "(" ParamList? ")" ("as" SequenceType)? (EnclosedExpr | "external")
[27]    ParamList    ::=    Param ("," Param)*
[28]    Param    ::=    "$" QName TypeDeclaration?
[29]    EnclosedExpr    ::=    "{" Expr "}"
[30]    QueryBody    ::=    Expr
[31]    Expr    ::=    ExprSingle ("," ExprSingle)*
[32]    ExprSingle    ::=    FLWORExpr
| QuantifiedExpr
| TypeswitchExpr
| IfExpr
| InsertExpr
| DeleteExpr
| RenameExpr
| ReplaceExpr
| TransformExpr
| OrExpr
[33]    FLWORExpr    ::=    (ForClause | LetClause)+ WhereClause? OrderByClause? "return" ExprSingle
[34]    ForClause    ::=    "for" "$" VarName TypeDeclaration? PositionalVar? "in" ExprSingle ("," "$" VarName TypeDeclaration? PositionalVar? "in" ExprSingle)*
[35]    PositionalVar    ::=    "at" "$" VarName
[36]    LetClause    ::=    "let" "$" VarName TypeDeclaration? ":=" ExprSingle ("," "$" VarName TypeDeclaration? ":=" ExprSingle)*
[37]    WhereClause    ::=    "where" ExprSingle
[38]    OrderByClause    ::=    (("order" "by") | ("stable" "order" "by")) OrderSpecList
[39]    OrderSpecList    ::=    OrderSpec ("," OrderSpec)*
[40]    OrderSpec    ::=    ExprSingle OrderModifier
[41]    OrderModifier    ::=    ("ascending" | "descending")? ("empty" ("greatest" | "least"))? ("collation" URILiteral)?
[42]    QuantifiedExpr    ::=    ("some" | "every") "$" VarName TypeDeclaration? "in" ExprSingle ("," "$" VarName TypeDeclaration? "in" ExprSingle)* "satisfies" ExprSingle
[43]    TypeswitchExpr    ::=    "typeswitch" "(" Expr ")" CaseClause+ "default" ("$" VarName)? "return" ExprSingle
[44]    CaseClause    ::=    "case" ("$" VarName "as")? SequenceType "return" ExprSingle
[45]    IfExpr    ::=    "if" "(" Expr ")" "then" ExprSingle "else" ExprSingle
[46]    OrExpr    ::=    AndExpr ( "or" AndExpr )*
[47]    AndExpr    ::=    ComparisonExpr ( "and" ComparisonExpr )*
[48]    ComparisonExpr    ::=    RangeExpr ( (ValueComp
| GeneralComp
| NodeComp) RangeExpr )?
[49]    RangeExpr    ::=    AdditiveExpr ( "to" AdditiveExpr )?
[50]    AdditiveExpr    ::=    MultiplicativeExpr ( ("+" | "-") MultiplicativeExpr )*
[51]    MultiplicativeExpr    ::=    UnionExpr ( ("*" | "div" | "idiv" | "mod") UnionExpr )*
[52]    UnionExpr    ::=    IntersectExceptExpr ( ("union" | "|") IntersectExceptExpr )*
[53]    IntersectExceptExpr    ::=    InstanceofExpr ( ("intersect" | "except") InstanceofExpr )*
[54]    InstanceofExpr    ::=    TreatExpr ( "instance" "of" SequenceType )?
[55]    TreatExpr    ::=    CastableExpr ( "treat" "as" SequenceType )?
[56]    CastableExpr    ::=    CastExpr ( "castable" "as" SingleType )?
[57]    CastExpr    ::=    UnaryExpr ( "cast" "as" SingleType )?
[58]    UnaryExpr    ::=    ("-" | "+")* ValueExpr
[59]    ValueExpr    ::=    ValidateExpr | PathExpr | ExtensionExpr
[60]    GeneralComp    ::=    "=" | "!=" | "<" | "<=" | ">" | ">="
[61]    ValueComp    ::=    "eq" | "ne" | "lt" | "le" | "gt" | "ge"
[62]    NodeComp    ::=    "is" | "<<" | ">>"
[63]    ValidateExpr    ::=    "validate" ValidationMode? "{" Expr "}"
[64]    ValidationMode    ::=    "lax" | "strict"
[65]    ExtensionExpr    ::=    Pragma+ "{" Expr? "}"
[66]    Pragma    ::=    "(#" S? QName (S PragmaContents)? "#)" /* ws: explicitXQ */
[67]    PragmaContents    ::=    (Char* - (Char* '#)' Char*))
[68]    PathExpr    ::=    ("/" RelativePathExpr?)
| ("//" RelativePathExpr)
| RelativePathExpr
/* gn: leading-lone-slashXQ */
[69]    RelativePathExpr    ::=    StepExpr (("/" | "//") StepExpr)*
[70]    StepExpr    ::=    FilterExpr | AxisStep
[71]    AxisStep    ::=    (ReverseStep | ForwardStep) PredicateList
[72]    ForwardStep    ::=    (ForwardAxis NodeTest) | AbbrevForwardStep
[73]    ForwardAxis    ::=    ("child" "::")
| ("descendant" "::")
| ("attribute" "::")
| ("self" "::")
| ("descendant-or-self" "::")
| ("following-sibling" "::")
| ("following" "::")
[74]    AbbrevForwardStep    ::=    "@"? NodeTest
[75]    ReverseStep    ::=    (ReverseAxis NodeTest) | AbbrevReverseStep
[76]    ReverseAxis    ::=    ("parent" "::")
| ("ancestor" "::")
| ("preceding-sibling" "::")
| ("preceding" "::")
| ("ancestor-or-self" "::")
[77]    AbbrevReverseStep    ::=    ".."
[78]    NodeTest    ::=    KindTest | NameTest
[79]    NameTest    ::=    QName | Wildcard
[80]    Wildcard    ::=    "*"
| (NCName ":" "*")
| ("*" ":" NCName)
/* ws: explicitXQ */
[81]    FilterExpr    ::=    PrimaryExpr PredicateList
[82]    PredicateList    ::=    Predicate*
[83]    Predicate    ::=    "[" Expr "]"
[84]    PrimaryExpr    ::=    Literal | VarRef | ParenthesizedExpr | ContextItemExpr | FunctionCall | OrderedExpr | UnorderedExpr | Constructor
[85]    Literal    ::=    NumericLiteral | StringLiteral
[86]    NumericLiteral    ::=    IntegerLiteral | DecimalLiteral | DoubleLiteral
[87]    VarRef    ::=    "$" VarName
[88]    VarName    ::=    QName
[89]    ParenthesizedExpr    ::=    "(" Expr? ")"
[90]    ContextItemExpr    ::=    "."
[91]    OrderedExpr    ::=    "ordered" "{" Expr "}"
[92]    UnorderedExpr    ::=    "unordered" "{" Expr "}"
[93]    FunctionCall    ::=    QName "(" (ExprSingle ("," ExprSingle)*)? ")" /* gn: reserved-function-namesXQ */
/* gn: parensXQ */
[94]    Constructor    ::=    DirectConstructor
| ComputedConstructor
[95]    DirectConstructor    ::=    DirElemConstructor
| DirCommentConstructor
| DirPIConstructor
[96]    DirElemConstructor    ::=    "<" QName DirAttributeList ("/>" | (">" DirElemContent* "</" QName S? ">")) /* ws: explicitXQ */
[97]    DirAttributeList    ::=    (S (QName S? "=" S? DirAttributeValue)?)* /* ws: explicitXQ */
[98]    DirAttributeValue    ::=    ('"' (EscapeQuot | QuotAttrValueContent)* '"')
| ("'" (EscapeApos | AposAttrValueContent)* "'")
/* ws: explicitXQ */
[99]    QuotAttrValueContent    ::=    QuotAttrContentChar
| CommonContent
[100]    AposAttrValueContent    ::=    AposAttrContentChar
| CommonContent
[101]    DirElemContent    ::=    DirectConstructor
| CDataSection
| CommonContent
| ElementContentChar
[102]    CommonContent    ::=    PredefinedEntityRef | CharRef | "{{" | "}}" | EnclosedExpr
[103]    DirCommentConstructor    ::=    "<!--" DirCommentContents "-->" /* ws: explicitXQ */
[104]    DirCommentContents    ::=    ((Char - '-') | ('-' (Char - '-')))* /* ws: explicitXQ */
[105]    DirPIConstructor    ::=    "<?" PITarget (S DirPIContents)? "?>" /* ws: explicitXQ */
[106]    DirPIContents    ::=    (Char* - (Char* '?>' Char*)) /* ws: explicitXQ */
[107]    CDataSection    ::=    "<![CDATA[" CDataSectionContents "]]>" /* ws: explicitXQ */
[108]    CDataSectionContents    ::=    (Char* - (Char* ']]>' Char*)) /* ws: explicitXQ */
[109]    ComputedConstructor    ::=    CompDocConstructor
| CompElemConstructor
| CompAttrConstructor
| CompTextConstructor
| CompCommentConstructor
| CompPIConstructor
[110]    CompDocConstructor    ::=    "document" "{" Expr "}"
[111]    CompElemConstructor    ::=    "element" (QName | ("{" Expr "}")) "{" ContentExpr? "}"
[112]    ContentExpr    ::=    Expr
[113]    CompAttrConstructor    ::=    "attribute" (QName | ("{" Expr "}")) "{" Expr? "}"
[114]    CompTextConstructor    ::=    "text" "{" Expr "}"
[115]    CompCommentConstructor    ::=    "comment" "{" Expr "}"
[116]    CompPIConstructor    ::=    "processing-instruction" (NCName | ("{" Expr "}")) "{" Expr? "}"
[117]    SingleType    ::=    AtomicType "?"?
[118]    TypeDeclaration    ::=    "as" SequenceType
[119]    SequenceType    ::=    ("empty-sequence" "(" ")")
| (ItemType OccurrenceIndicator?)
[120]    OccurrenceIndicator    ::=    "?" | "*" | "+" /* gn: occurrence-indicatorsXQ */
[121]    ItemType    ::=    KindTest | ("item" "(" ")") | AtomicType
[122]    AtomicType    ::=    QName
[123]    KindTest    ::=    DocumentTest
| ElementTest
| AttributeTest
| SchemaElementTest
| SchemaAttributeTest
| PITest
| CommentTest
| TextTest
| AnyKindTest
[124]    AnyKindTest    ::=    "node" "(" ")"
[125]    DocumentTest    ::=    "document-node" "(" (ElementTest | SchemaElementTest)? ")"
[126]    TextTest    ::=    "text" "(" ")"
[127]    CommentTest    ::=    "comment" "(" ")"
[128]    PITest    ::=    "processing-instruction" "(" (NCName | StringLiteral)? ")"
[129]    AttributeTest    ::=    "attribute" "(" (AttribNameOrWildcard ("," TypeName)?)? ")"
[130]    AttribNameOrWildcard    ::=    AttributeName | "*"
[131]    SchemaAttributeTest    ::=    "schema-attribute" "(" AttributeDeclaration ")"
[132]    AttributeDeclaration    ::=    AttributeName
[133]    ElementTest    ::=    "element" "(" (ElementNameOrWildcard ("," TypeName "?"?)?)? ")"
[134]    ElementNameOrWildcard    ::=    ElementName | "*"
[135]    SchemaElementTest    ::=    "schema-element" "(" ElementDeclaration ")"
[136]    ElementDeclaration    ::=    ElementName
[137]    AttributeName    ::=    QName
[138]    ElementName    ::=    QName
[139]    TypeName    ::=    QName
[140]    URILiteral    ::=    StringLiteral
[141]    RevalidationDecl    ::=    "declare" "revalidation" ("strict" | "lax" | "skip")
[142]    InsertExpr    ::=    "do" "insert" SourceExpr ((("as" ("first" | "last"))? "into")
| "after"
| "before") TargetExpr
[143]    DeleteExpr    ::=    "do" "delete" TargetExpr
[144]    ReplaceExpr    ::=    "do" "replace" ("value" "of")? TargetExpr "with" ExprSingle
[145]    RenameExpr    ::=    "do" "rename" TargetExpr "as" NewNameExpr
[146]    SourceExpr    ::=    ExprSingle
[147]    TargetExpr    ::=    ExprSingle
[148]    NewNameExpr    ::=    ExprSingle
[149]    TransformExpr    ::=    "transform" "copy" "$" VarName ":=" ExprSingle ("," "$" VarName ":=" ExprSingle)* "modify" ExprSingle "return" ExprSingle

A.1 Terminal Symbols

[150]    IntegerLiteral    ::=    Digits
[151]    DecimalLiteral    ::=    ("." Digits) | (Digits "." [0-9]*) /* ws: explicitXQ */
[152]    DoubleLiteral    ::=    (("." Digits) | (Digits ("." [0-9]*)?)) [eE] [+-]? Digits /* ws: explicitXQ */
[153]    StringLiteral    ::=    ('"' (PredefinedEntityRef | CharRef | EscapeQuot | [^"&])* '"') | ("'" (PredefinedEntityRef | CharRef | EscapeApos | [^'&])* "'") /* ws: explicitXQ */
[154]    PredefinedEntityRef    ::=    "&" ("lt" | "gt" | "amp" | "quot" | "apos") ";" /* ws: explicitXQ */
[155]    EscapeQuot    ::=    '""'
[156]    EscapeApos    ::=    "''"
[157]    ElementContentChar    ::=    Char - [{}<&]
[158]    QuotAttrContentChar    ::=    Char - ["{}<&]
[159]    AposAttrContentChar    ::=    Char - ['{}<&]
[160]    Comment    ::=    "(:" (CommentContents | Comment)* ":)" /* ws: explicitXQ */
/* gn: commentsXQ */
[161]    PITarget    ::=    [http://www.w3.org/TR/REC-xml#NT-PITarget]XML /* gn: xml-versionXQ */
[162]    CharRef    ::=    [http://www.w3.org/TR/REC-xml#NT-CharRef]XML /* gn: xml-versionXQ */
[163]    QName    ::=    [http://www.w3.org/TR/REC-xml-names/#NT-QName]Names /* gn: xml-versionXQ */
[164]    NCName    ::=    [http://www.w3.org/TR/REC-xml-names/#NT-NCName]Names /* gn: xml-versionXQ */
[165]    S    ::=    [http://www.w3.org/TR/REC-xml#NT-S]XML /* gn: xml-versionXQ */
[166]    Char    ::=    [http://www.w3.org/TR/REC-xml#NT-Char]XML /* gn: xml-versionXQ */

The following symbols are used only in the definition of terminal symbols; they are not terminal symbols in the grammar of A EBNF for XQuery 1.0 Grammar with Update extensions.

[167]    Digits    ::=    [0-9]+
[168]    CommentContents    ::=    (Char+ - (Char* ('(:' | ':)') Char*))

B References

B.1 Normative References

XQuery Update Facility Requirements
World Wide Web Consortium. XQuery Update Facility Requirements. W3C Working Draft, 03 June 2005. See http://www.w3.org/TR/xquery-update-requirements.
XQuery/XPath Data Model (XDM)
World Wide Web Consortium. XQuery 1.0 and XPath 2.0 Data Model (XDM). W3C Working Draft, 03 November 2005. See http://www.w3.org/TR/xpath-datamodel/.
XQuery 1.0
World Wide Web Consortium. XQuery 1.0: An XML Query Language. W3C Working Draft, 03 November 2005. See http://www.w3.org/TR/xquery/.

B.2 Non-normative References

(None so far.)

C Error Conditions

err:XUST0001

It is a static error if an updating expression is used in any position other than one of the following:

  1. The topmost expression in the body of a query.

  2. The modify clause of a transform expression.

  3. The return clause of a FLWOR expression.

  4. The return clauses of a typeswitch expression in which every return clause and contains an updating expression, an empty expression ( ), or a call to the fn:error function.

  5. The then and else clauses of a conditional statement in which both the then and else clauses contain either an updating expression, an empty expression ( ), or a call to the fn:error function.

  6. An operand of a comma expression in which each operand is either an updating expression, an empty expression ( ), or a call to the fn:error function.

  7. The content of a parenthesized expression.

  8. The body of a function declaration in which the keyword updating is specified.

err:XUST0002

It is a static error if an non-updating expression other than an empty expression ( ) or a call to the fn:error function is used in one of the following positions:

  1. The modify clause of a transform expression.

  2. The top-level expression in the body of a function declaration in which the keyword updating is specified.

D Glossary (Non-Normative)

basic updating expression

A basic updating expression is an insert, delete, replace, or rename expression, or a call to an updating function.

data model

The term data model refers to the data model specified by [XQuery/XPath Data Model (XDM)].

mark

To mark a node means to identify the node as participating in a later operation.

non-updating expression

A non-updating expression is any XQuery expression that is not an updating expression.

pending update list

A pending update list is an unordered collection of update primitives, which represent node state changes that have not yet been applied.

revalidation declaration

A revalidation declaration sets the revalidation mode in the static context, overriding any implementation-defined default.

revalidation mode

Revalidation mode, which may be strict, lax, or skip, is a component of the static context that controls the behavior of the upd:revalidate operation.

snapshot semantics

The upd:applyUpdates operation determines the scope within which all expressions are evaluated before any updates are applied. This is sometimes called the scope of snapshot semantics.

target node

The first argument of an update primitive, called its target node, is the principal node to be affected by the update primitive.

update operation

Update operations are used in defining the semantics of XQuery updates, but are not directly available to users. Update operations are defined in 3 Update Operations.

update primitive

Update primitives are the components of pending update lists. Each update primitive represents a node state change that has not yet been applied.

update routine

Update routines are sequences of actions that are used in the definition of XQuery semantics but do not appear on pending update lists.

updating expression

An updating expression is an expression that contains a basic updating expression that is not inside the modify clause of a transform expression.

XDM instance

The term XDM instance denotes an unconstrained sequence of zero or more nodes and/or atomic values as defined by the data model.

XQuery

Within this document, the term XQuery refers to the language specified by [XQuery 1.0].

E Revision Log (Non-Normative)

This log records the substantive changes that have been made to this document since the Initial Working Draft of 27 January 2006. Minor editorial changes are not included in this log.

E.1 8 May 2006 Version

  1. Grammar changes:

    1. Add do as initial keyword in InsertExpr, DeleteExpr, ReplaceExpr, RenameExpr.

    2. Eliminate curly braces around first operands of all updating expressions (as a result, DirectConstructor is no longer a special case in InsertExpr).

    3. Eliminate do keyword from FLWOR and typeswitch expressions (any updating subexpressions must be in the return clause).

    4. In TransformExpr, change do keyword to modify, and change ExprSingle to Expr in modify-clause.

    5. In ReplaceExpr, keep only a single action-clause (earlier syntax allowed one or more action-clauses).

    6. In RenameExpr, change to keyword to as (avoids an ambiguity).

  2. A comma expression no longer permits its operands to include a mixture of updating and non-updating expressions.

  3. In a function declaration, if updating is specified, the function does not return a value, and no result type may be declared.

  4. Added clarifying details:

    1. It is a static error if the operand expression of a typeswitch is an updating expression.

    2. if (text) then ( ) else ( )is a non-updating expression.

    3. An empty parenthesized expression ( ) is a non-updating expression.

    4. The body of an updating function may contain an empty expression ( ) or a call to the fn:error function.

  5. Specified that upd:applyUpdates is an atomic operation with respect to the data model, but that propagation of data model changes to an underlying physical representation is beyond the scope of this specification.

  6. Eliminated the incompatibility between primitive operations insert into and insert into as last when these operations are applied to the same target node.

  7. Replaced all occurrences of the xdt: namespace prefix with xs:, following a joint decision by the Query and XSLT Working Groups.

E.2 11 July 2006 Version

  1. Simplification of the rules for compatibility of updating expressions. Creates three new update primitives: upd:insertAsFirst, upd:replaceNode, and upd:replaceValue. Eliminates the compatibility table and introduces new mappings of XQuery updating expressions onto update primitives as suggested in http://lists.w3.org/Archives/Member/member-query-ultf/2006Mar/0028.html. Introduces new definition of upd:applyUpdates, removing many incompatibilities.

  2. More specific definition of the upd:revalidate update operation.

  3. More formal definitions of updating and non-updating expressions.

  4. Corrections to error XUST0001 (formerly XUST0101) and definition of a new error XUST0002.

  5. Define replacement of a node as substitution of new nodes in the position of the original node. As a result, an attribute node can be replaced only by attribute nodes, and content (element, text, comment, and PI) nodes can be replaced only by content nodes.

  6. Revised the mappings of replace expressions onto underlying primitives to make the compatibility rules more consistent. The new mappings require one new update primitive, called upd:replaceElementContent, which is applied immediately before the final deletion of nodes that are marked for deletion by other primitives.

  7. Created new subheadings inside the "Replace" section to call attention to the two forms of a replace expression (editorial change).

  8. Added the function fn:put for storing a document or element to a location.