W3C

XQuery Scripting Extension 1.0

W3C Working Draft 28 March 2008

This version:
http://www.w3.org/TR/2008/WD-xquery-sx-10-20080328/
Latest version:
http://www.w3.org/TR/xquery-sx-10/
Editors:
Don Chamberlin, IBM Almaden Research Center, via http://www.almaden.ibm.com/cs/people/chamberlin/
Daniel Engovatov, BEA Systems <dengovatov@bea.com>
Dana Florescu, Oracle Corporation <dana.florescu@oracle.com>
Giorgio Ghelli, University of Pisa <ghelli@di.unipi.it>
Jim Melton, Oracle Corporation <jim.melton@acm.org>
Jérôme Siméon, IBM T.J. Watson Research Center <simeon@us.ibm.com>

Abstract

This specification defines an extension to [XQuery 1.0] and [XQuery Update Facility]. Expressions can be evaluated in a specific order, with later expressions seeing the effects of the expressions that came before them. This specification introduces the concept of a block with local variable declarations, as well as several new kinds of expressions, including assignment, while, continue, break, and exit expressions.

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 is a First Public Working Draft as described in the Process Document. It has been developed by the W3C XML Query Working Group, which is part of the XML Activity. The Working Group expects to advance this specification to Recommendation Status.

This document, published on 28 March 2008, represents the current status of its development. The WG believes that its development is sufficiently advanced to make it publicly visible to the community, who we hope will review it and submit comments on it. We particularly call your attention to our open E Issues.

No implementation report currently exists. However, a Test Suite for this document is under development.

Please report errors in this document using W3C's public Bugzilla system (instructions can be found at http://www.w3.org/XML/2005/04/qt-bugzilla). If access to that system is not feasible, you may send your comments to the W3C XSLT/XPath/XQuery public comments mailing list, public-qt-comments@w3.org. It will be very helpful if you include the string “[SX]” in the subject line of your report, whether made in Bugzilla or in email. Each Bugzilla entry and email message should contain only one error report. Archives of the comments and responses are available at http://lists.w3.org/Archives/Public/public-qt-comments/.

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.

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.2.1 Constants and Variables
        2.2.2 Function Declarations
    2.3 New Kinds of Expressions
        2.3.1 Assignment Expression
        2.3.2 Block
        2.3.3 Exit Expression
        2.3.4 While Expression
        2.3.5 Continue and Break Expressions
    2.4 Changes to Existing Expressions
        2.4.1 Function Calls
        2.4.2 FLWOR Expressions
        2.4.3 Conditional Expressions
        2.4.4 Typeswitch Expressions
        2.4.5 Comma Expressions
        2.4.6 Parentheses
        2.4.7 Ordered and Unordered Expressions
        2.4.8 Transform Expressions
        2.4.9 Extension Expressions
        2.4.10 Other Expressions
3 Example

Appendices

A Summary of XQSE Grammar Changes
B XML Syntax (XQueryX) for XQuery Scripting Extension 1.0
    B.1 Schema
    B.2 Stylesheet
    B.3 Example
        B.3.1 XQuery Representation
        B.3.2 XQueryX Representation
        B.3.3 Transformed XQuery Representation
C Implementation-Defined Items
D References
E Issues


1 Introduction

XQuery Scripting Extension extends [XQuery 1.0], enabling it to serve as a scripting language in order to satisfy [XQuery Scripting Requirements]. A prerequisite for this extension is [XQuery Update Facility]. The following abbreviations are used in this specification: [Definition: XQUF is an abbreviation for [XQuery Update Facility].] [Definition: XQSE is an abbreviation for XQuery Scripting Extension.]

XQSEhas the following properties:

The principal extensions introduced by XQSE are as follows:

  1. An ordering is defined on the evaluation of certain kinds of XQuery expressions. An implementation may use any execution strategy as long as the result complies with the semantics of this ordering. The ordering is defined in a way that places no additional constraints on the evaluation of any existing expressions.

  2. Expressions in XQSE may have side-effects that are visible to subsequent expressions (according to the above ordering of evaluation).

  3. XQSEintroduces the following new kinds of expressions:

    1. Assignment expressions

    2. Blocks

    3. Exit expressions

    4. While expressions

    5. Continue expressions

    6. Break expressions

  4. XQSEintroduces a new expression category called sequential expressions. The expression categories introduced by XQUF (updating, simple, and vacuous expressions) are retained. Informal definitions of all the expression categories are summarized here. For normative definitions of the categories, see the "Category Rules" that are specified for each kind of expression in 2.3 New Kinds of Expressions and 2.4 Changes to Existing Expressions.

    1. [Definition: An updating expression is an expression that can return a non-empty pending update list.] Updating expressions include insert, delete, replace, rename, and calls to updating functions, as well as certain other expressions that contain nested updating expressions. Note that, although an updating expression may return a non-empty pending update list, it does not actually apply any updates.

    2. [Definition: A sequential expression is an expression that can have side effects other than constructing a new node or raising an error.] Side effects include applying updates to an XDM instance, altering the dynamic context, or affecting the flow of control. Sequential expressions include blocks, assignment, exit, while, continue, break, and calls to sequential functions, as well as certain other expressions that contain nested sequential expressions. The side effects of a sequential expression are immediately effective and are visible to subsequent expressions. Because of their side effects, sequential expressions must be evaluated in a well-defined order. In addition to its side effects, a sequential expression may return a non-empty XDM instance, but it never returns a non-empty pending update list.

    3. [Definition: A simple expression is an expression that is neither an updating expression nor a sequential expression.] A simple expression may return an XDM instance, and it may construct a node or raise an error.

    4. [Definition: A vacuous expression is a simple expression that can only return an empty sequence or raise an error.]

    The classification of each expression into one of the above categories is performed by static analysis. For each kind of expression, XQSE provides rules that specify the required categories of the operand expressions and the category of the expression itself.

Note that simple expressions, updating expressions, and sequential expressions are disjoint categories, and that vacuous expressions are a subset of simple expressions. The kinds of values that can be returned by the various expression categories are summarized in the following table:

Expression category Can return non-empty XDM instance? Can return non-empty PUL?
Simple YES NO
Updating NO YES
Sequential YES NO
Vacuous NO NO

2 Extensions to XQuery 1.0

2.1 Extensions to the Processing Model

XQSEdefines an ordering on the evaluation of certain kinds of XQuery expressions. An implementation may use any execution strategy as long as the result complies with the semantics of this ordering. Since some of the expressions introduced by XQSE have immediate side effects, a well-defined evaluation order is necessary for a deterministic result.

XQSEsemantics are defined by the following evaluation order:

FLWOR:for, let, where, and order-by clauses are evaluated first, generating a tuple stream. Then the return clause is evaluated multiple times in the order of the tuple stream. If the return clause contains a sequential expression, the side effects of each iteration are visible to subsequent iterations.

Function calls:Argument expressions are evaluated before the function body.

If-then-else:The if-clause is evaluated first. Next, either the then-clause, or the else-clause (but not both), is evaluated.

Typeswitch:The switch-expression is evaluated first. Then, exactly one of the return-clauses is evaluated.

Concatenate (comma):Operand expressions are evaluated once, from left to right. Side effects of each sequential operand expression are visible to subsequent operand expressions.

Block:Variable declarations are evaluated first, in the order written; then the expressions in the body are evaluated, in the order written. The pending update list (if any) returned by each body expression is made effective before evaluation of the next body expression. XDM updates and side effects generated by each body expression are visible to subsequent body expressions.

While:The test expression is evaluated first. If its effective Boolean value is false, the body is not evaluated. If the effective Boolean value of the test expression is true, the body is evaluated repeatedly until the value of the test expression becomes false or until a break or exit expression is encountered. Side effects of each iteration are visible to subsequent iterations.

Note:

Since none of the XQuery expressions existing before XQSE has any immediate side-effects, no ordering is effectively imposed on the evaluation of any XQuery unless it contains one of the new expressions introduced by XQSE.

The term snapshot is defined in [XQuery Update Facility] as follows: [Definition: A snapshot is a scope within which expressions are evaluated with respect to a fixed XDM instance and updates are held pending.] A snapshot is terminated by invocation of the upd:applyUpdates operation. Unlike XQUF, XQSE permits a query to contain more than one snapshot. In XQSE, each expression within a block constitutes a separate snapshot. If blocks are nested, snapshots are defined by the innermost nested block.

Like [XQuery Update Facility], this specification defines the semantics of operations on an XDM instance. Propagation of changes to an underlying persistent store (if any) is beyond the scope of this specification. Thus, for example, it is implementation-defined whether the effects of an fn:put function are visible to an fn:doc, fn:doc-available, or fn:collection function executed in a subsequent snapshot.

2.2 Extensions to the Prolog

2.2.1 Constants and Variables

[Definition: XQSEallows the keyword constant to be used in place of variable in a Prolog declaration. A variable declared in this way is called a constant.]

VarDecl ::= "declare" ("variable" | "constant") "$" QName TypeDeclaration?
          ((":=" ExprSingle) | "external")

Rules for initializing variables and for determining the scope of variables apply equally to constants. The semantics of constants are the same as the semantics of variables, with the following exception: It is a static error [err:TBD] if a constant appears on the left-hand-side of an assignment expression.

The initializing expression in a variable or constant declaration in a Prolog must be a simple expression [err:TBD].

2.2.2 Function Declarations

FunctionDecl ::= "declare" "simple"? "function" QName "(" ParamList? ")"
          ("as" SequenceType)? (EnclosedExpr | "external")
   | "declare" "updating" "function" QName "(" ParamList? ")"
          (EnclosedExpr | "external")
   | "declare" "sequential" "function" QName "(" ParamList? ")"
          ("as" SequenceType)? (Block | "external")
Definitions:

[Definition: A simple function is a function whose declaration specifies neither updating nor sequential.]

[Definition: An updating function is a function whose declaration specifies the keyword updating.]

[Definition: A sequential function is a function whose declaration specifies the keyword sequential.]

Category Rules:

The EnclosedExpr in the body of a simple function (if any) must be a simple expression.

The EnclosedExpr in the body of an updating function (if any) must be an updating or vacuous expression.

The body of a sequential function (if any) is a Block, which is a sequential expression.

Semantics:

The semantics of simple functions are defined in [XQuery 1.0].

The semantics of updating functions are defined in [XQuery Update Facility].

The semantics of sequential functions are as follows:

  • If the body of a sequential function contains a Block, the result of the function is determined by the first exit expression encountered during evaluation of the Block. If no exit expression is encountered, the result of the function is an empty sequence.

  • If the result of a sequential function does not match its declared result type (after applying function conversion rules as specified in Section 3.1.5 Function CallsXQ), a type error is raised [err:XPTY0004]. The default result type of a sequential function is item()*.

  • If a sequential function is declared external, its implementation is outside the XQuery environment. The means by which parameters are passed to an external function and its result is returned to the calling expression are implementation-defined. An external sequential function may not return a non-empty pending update list [err:TBD].

2.3 New Kinds of Expressions

XQSEextends the XQuery 1.0 syntax by adding several new kinds of expressions. The effect of these new expressions on the XQuery grammar is as follows:

ExprSingle ::= (all existing options)
   | AssignmentExpr 
   | Block
   | ExitExpr 
   | WhileExpr
   | ContinueExpr
   | BreakExpr

2.3.1 Assignment Expression

AssignmentExpr ::= "set" "$" VarName ":=" ExprSingle
Category Rules:

The expression on the right-hand-side of an assignment may not be an updating expression (it may be a simple expression or a sequential expression.)

An assignment expression is a sequential expression.

Semantics:

The variable on the left-hand side of the assignment must have been declared by a variable declaration, either in an enclosing block or in the Prolog, and it must be in scope [err:TBD].

Note:

Variables bound in FLWOR, typeswitch, or quantified expressions may not appear on the left-hand side of an assignment.

The expression on the right-hand side is evaluated. If the XDM instance returned by this expression does not match the declared type of the variable according to SequenceType matching rules, a type error is raised [err:TBD]. If the types match, the XDM instance returned by the expression is bound to the variable (added to variable values in the dynamic context.)

The result of an Assignment Expression is an empty XDM instance and an empty pending update list.

2.3.2 Block

Block ::= "{" BlockDecls BlockBody "}"

BlockDecls ::= (BlockVarDecl ";")*

BlockVarDecl ::= "declare" "$" VarName TypeDeclaration? (":=" ExprSingle)? 
     ("," "$" VarName TypeDeclaration? (":=" ExprSingle)? )*

BlockBody ::= (Expr ";")*
Category Rules:

The expressions on the right-hand-sides of block variable declarations must not be updating expressions.

Note:

Block variable declarations, unlike Prolog variable declarations, permit their initializing expressions to be sequential expressions.

The expressions in the body of the block may be in any category.

A block is a sequential expression.

Semantics:

A block consists of zero or more block variable declarations followed by a body. Each block variable declaration defines a local variable whose scope is the remainder of the block (not including its initializing expression). The variable defined in a block variable declaration occludes (hides) any variable of the same name that is in scope at the location where the block appears.

The block variable declarations are evaluated in the order written. [Definition: The expression on the right-hand side of a block variable declaration is called an initializing expression.] The block variable declaration evaluates its initializing expression and adds the resulting value to variable values in the dynamic context. If no initializing expression is present, the variable has no initial value. A reference to a variable, other than on the left-hand side of an assignment expression, is an error if the variable has no value in variable values when the reference is evaluated [err:TBD].

The type of each declared variable is added to in-scope variables in the static context. If no explicit type is declared, the type of the variable is inferred from the type of its initializing expression. If the variable has neither an explicit type declaration nor an initializing expression, its type is item()*. If a variable has both an explicit type declaration and an initializing expression, the value of the initializing expression must match the declared type according to SequenceType matching rules; otherwise a type error is raised [err:TBD].

It is a static error [err:TBD] if two or more variables declared in the same block have the same expanded QName.

After all the block variable declarations have been evaluated, the body is evaluated. The body consists of one or more expressions, separated by semicolons (the final expression may optionally be followed by a semicolon.) The expressions in the body are evaluated in the order they appear. After the evaluation of each expression, the pending update list returned by the expression (if any) is applied (by upd:applyUpdates), and the XDM instance returned by the expression (if any) is discarded. The side effects of each expression are visible during the evaluation of subsequent expressions.

The result of a block is an empty XDM instance and an empty pending update list.

2.3.3 Exit Expression

ExitExpr ::= "exit" "with" ExprSingle
Category Rules:

The operand of an exit expression must not be an updating expression.

If an exit expression is in the body of a function declaration, that function declaration must not specify updating [err:TBD].

An exit expression is a sequential expression.

Semantics:

An exit expression serves to define the result of the enclosing function or query body.

If an exit expression is evaluated within the body of a function, further evaluation of the function body is interrupted and the XDM instance returned by the operand expression is returned as the result of the function call.

If an exit expression is evaluated within a query body (i.e., not within the body of a function), further evaluation of the query is interrupted and the XDM instance returned by the operand expression is returned as the result of the query.

Note:

An exit expression in a block terminates evaluation of the enclosing function body or query, not just the immediately enclosing block.

2.3.4 While Expression

WhileExpr ::= "while" "(" ExprSingle ")" Block
Category Rules:

The expression enclosed in parentheses, called the test expression, may not be an updating expression.

A while expression is a sequential expression.

Semantics:

The while expression is used for conditional iteration. It is evaluated as follows:

First, the test expression is evaluated. If its effective Boolean value is false, the block is not evaluated. If the effective Boolean value of the test expression is true, the block is evaluated repeatedly. Each evaluation of the block may cause side effects that affect the test expression. The test expression is evaluated after each evaluation of the block. This process continues until the effective Boolean value of the test expression is evaluated to be false or until a break or exit expression is evaluated within the block.

The result of a while expression is an empty XDM instance and an empty pending update list.

Example:

In the following block, a while expression is used to compute a sequence containing all the Fibonacci numbers that are less than 100.

{ declare $a as xs:integer := 0;
  declare $b as xs:integer := 1;  
  declare $c as xs:integer := $a + $b;
  declare $fibseq as xs:integer* := ($a, $b);
 
  while ($c < 100) { 
     set $fibseq := ($figseq, $c);
     set $a := $b;
     set $b := $c;
     set $c := $a + $b;
  };

  exit with $fibseq;
}

2.3.5 Continue and Break Expressions

ContinueExpr ::= "continue" "loop"

BreakExpr ::= "break" "loop"
Category Rules:

Continue and break expressions are sequential expression.

Semantics:

Continue and break expressions provide convenient ways to control the evaluation of a while expression.

If a continue expression is evaluated, it interrupts the current iteration of the nearest enclosing while expression, and starts the next iteration.

If a break expression is evaluated, it halts the evaluation of the nearest enclosing while expression.

If a continue or break expression has no enclosing while expression, a static error is raised [err:TBD].

Note:

Continue and break expressions have no effect on evaluation of a FLWOR expression, even if they are contained in the return-clause of the FLWOR.

2.4 Changes to Existing Expressions

Since this proposal introduces a new category of expression (sequential expression), the existing expressions need to specify whether they accept expressions in the new category as operands. In some cases, the category of an expression is determined by the categories of its operands.

2.4.1 Function Calls

Category Rules:

The parameters of a function call must be simple expressions.

A call to the built-in function fn:error is a vacuous expression.

A call to an updating function is an updating expression.

A call to a sequential function is a sequential expression.

A call to any other function is a simple expression.

2.4.2 FLWOR Expressions

Category Rules:

The for, let, where, and order by clauses must contain simple expressions.

The return clause may contain any kind of expression.

The category of the FLWOR expression is the same as the category of the expression in its return clause.

Semantics:

The result of a FLWOR expression is the concatenation of the XDM instances or pending update lists returned by successive evaluations of the return clause, in evaluation order. Pending update lists are concatenated by the upd:mergeUpdates operation.

2.4.3 Conditional Expressions

Category Rules:

The expression in the if clause must be a simple expression.

Let the expressions in the then and else clauses be called branches. Then:

2.4.4 Typeswitch Expressions

Category Rules:

The expression following the typeswitch keyword must be a simple expression.

Let the expressions in the case and default clauses be called branches. Then:

2.4.5 Comma Expressions

Category Rules:

The category of a comma expression is determined by the following rules:

2.4.6 Parentheses

Category Rules:

Any category of expression may be enclosed in parentheses; the resulting expression has the same category as the original expression. An empty parenthesized expression ( ) is a vacuous expression.

2.4.7 Ordered and Unordered Expressions

Category Rules:

The operand of an ordered or unordered expression may be an expression of any category. The category of the ordered or unordered expression is the same as the category of its operand.

2.4.8 Transform Expressions

Category Rules:

The copy clause must contain a simple expression.

The modify clause must contain an updating or vacuous expression.

The return clause must contain a simple or sequential expression.

The category of the transform expression is the same as the category of its return clause.

2.4.9 Extension Expressions

Category Rules:

The operand of an extension expression may be an expression of any category. The category of the extension expression is the same as the category of its operand.

2.4.10 Other Expressions

Category Rules:

All expressions not listed above are simple expressions, and accept only simple expressions as their operands. This includes the following kinds of expressions:

  • Path expressions

  • Filter expressions

  • Range expressions

  • Union, intersect, and except expressions

  • Arithmetic, comparison, and logical expressions

  • Constructors of all kinds

  • Ordered and unordered expressions

  • Quantified expressions

  • Instance of, cast, castable, and treat expressions

  • Validate expressions

3 Example

The following function returns true or false according to whether its parameter is a known user name, and logs the event:

declare sequential function validate-and-log($username as xs:string) 
     as xs:boolean { 
        declare $log as document-node() := fn:doc("log.xml"); 
        declare $entry as element() :=
           <access-attempt>
              <timestamp>{fn:current-dateTime()}</timestamp>
              <user-name>{$username}</user-name>
              <access-allowed/>
           </access-attempt> ;
        declare $result as xs:boolean;
        if ($username = doc("users.xml")/current-users/user/name ) 
        then {
           replace value of node $entry/access-allowed with "Yes"; 
           set $result := true(); 
        } else { 
           replace value of node $entry/access-allowed with "No"; 
           set $result := false(); 
        } ; 
        insert node $entry as last into $log; 
        fn:put($log, "log.xml"); 
        exit with $result; 
} 

A Summary of XQSE Grammar Changes

VarDecl ::= "declare" ("variable" | "constant") "$" QName TypeDeclaration?
          ((":=" ExprSingle) | "external") 

ExprSingle ::= (all existing options)
   | AssignmentExpr 
   | Block
   | ExitExpr 
   | WhileExpr
   | ContinueExpr
   | BreakExpr 

AssignmentExpr ::= "set" "$" VarName ":=" ExprSingle 

Block ::= "{" BlockDecls BlockBody "}"

BlockDecls ::= (BlockVarDecl ";")*

BlockVarDecl ::= "declare" "$" VarName TypeDeclaration? (":=" ExprSingle)? 
     ("," "$" VarName TypeDeclaration? (":=" ExprSingle)? )*

BlockBody ::= (Expr ";")*

ExitExpr ::= "exit" "with" ExprSingle 

WhileExpr ::= "while" "(" ExprSingle ")" Block 

ContinueExpr ::= "continue" "loop"

BreakExpr ::= "break" "loop" 

FunctionDecl ::= "declare" "simple"? "function" QName "(" ParamList? ")"
          ("as" SequenceType)? (EnclosedExpr | "external")
   | "declare" "updating" "function" QName "(" ParamList? ")"
          (EnclosedExpr | "external")
   | "declare" "sequential" "function" QName "(" ParamList? ")"
          ("as" SequenceType)? (Block | "external")

B XML Syntax (XQueryX) for XQuery Scripting Extension 1.0

[XML Syntax for XQuery 1.0] defines an XML representation of [XQuery 1.0]. [XQuery Scripting Requirements] states "The syntax for updates MAY have more than one syntax binding. One syntax MUST be convenient for humans to read and write. One syntax MUST be expressed in XML in a way that reflects the underlying structure of the operations." This appendix specifies an XML Schema that defines the XML representation of XQuery Scripting Extension 1.0 by representing the abstract syntax found in A Summary of XQSE Grammar Changes. This XML representation for XQuery Scripting Extension 1.0 integrates with the XML representation for XQuery 1.0 and that for the XQuery Update Facility 1.0.

The XML Schema specified in this appendix accomplishes its integration by importing the XML Schema defined for XQueryX in [XQuery Update Facility], incorporating all of its type and element definitions. It then extends that schema by adding definitions of new types and elements in a namespace belonging to the XQuery Scripting Extension 1.0 specification.

B.1 Schema

This section specifies the XML Schema that defines the complex types and elements for XQueryX in support of XQuery Scripting Extension 1.0, including changes to the prolog and the addition of several new expressions. It also specifies a second XML Schema that redefines an element defined in XQueryX 1.0. Copies of these two schemata can be found at http://www.w3.org/2008/xquery-sx-10/xquery-sx-10-xqueryx.xsd. and http://www.w3.org/2008/xquery-sx-10/xquery-sx-10-xqueryx-redef.xsd. Please note that the content of these schemata are subject to change at any time before this document is published as a Recommendation.


<xsd:schema
     xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
     xmlns:xqx="http://www.w3.org/2005/XQueryX"
     xmlns:xqxuf="http://www.w3.org/2007/xquery-update-10"
     xmlns:xqxsx="http://www.w3.org/2008/xquery-sx-10"
     targetNamespace="http://www.w3.org/2008/xquery-sx-10"
     elementFormDefault="qualified" 
     attributeFormDefault="unqualified">

<!-- Initial creation                  2008-03-01: Jim Melton -->
<!-- Added FunctionDecl redefinition   2008-03-11: Jim Melton -->

  <xsd:import namespace="http://www.w3.org/2005/XQueryX"
     schemaLocation="http://www.w3.org/2008/xquery-sx-10/xquery-sx-10-xqueryx-redef.xsd"/>

  <!-- Declare new type for constant declarations             -->
  <xsd:complexType name="constDecl">
    <xsd:sequence>
      <xsd:element name="constName" type="xqx:QName"/>
      <xsd:element ref="xqx:typeDeclaration" minOccurs="0"/>
      <xsd:element name="constValue" type="xqx:exprWrapper"/>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:element name="constDecl" type="xqxsx:constDecl"
               substitutionGroup="xqx:prologPartTwoItem"/>


  <!-- Create substitution grp for scripting extension exprs  -->
  <xsd:complexType name="expr">
    <xsd:complexContent>
      <xsd:extension base="xqx:expr"/>
    </xsd:complexContent>
  </xsd:complexType>

  <!-- Make scripting extension subst grp part of expr grp    -->
  <xsd:element name="expr" type="xqxsx:expr" abstract="true"
               substitutionGroup="xqx:expr"/>


  <!-- AssignmentExpr:                                        -->
  <!--   AssignmentExpr ::= "set" "$" VarName ":=" ExprSingle -->
  <xsd:complexType name="assignmentExpr">
    <xsd:complexContent>
      <xsd:extension base="xqxsx:expr">
        <xsd:sequence>
          <xsd:element ref="xqx:positionalVariableBinding"/>
          <xsd:element name="assignedExpr" type="xqx:exprWrapper"/>
        </xsd:sequence>
      </xsd:extension>
    </xsd:complexContent>
  </xsd:complexType>

  <xsd:element name="assignmentExpr" type="xqxsx:assignmentExpr"
               substitutionGroup="xqxsx:expr"/>


  <!-- Block (1 of 3):                                        -->
  <!--   Block ::= "{" BlockDecls BlockBody "}"               -->
  <!--   BlockDecls ::= (BlockVarDecl ";")*                   -->
  <xsd:complexType name="block">
    <xsd:complexContent>
      <xsd:extension base="xqxsx:expr">
        <xsd:sequence>
          <xsd:element ref="xqxsx:blockVarDecl"
                       minOccurs="0" maxOccurs="unbounded"/>
          <xsd:element ref="xqxsx:blockBody"/>
        </xsd:sequence>
      </xsd:extension>
    </xsd:complexContent>
  </xsd:complexType>

  <xsd:element name="block" type="xqxsx:block"
               substitutionGroup="xqxsx:expr"/>

  <!-- Block (2 of 3):                                        -->
  <!--   BlockVarDecl ::=                                     -->
  <!--     "declare" "$" VarName TypeDeclaration?             -->
  <!--             (":=" ExprSingle)?                         -->
  <!--          ("," "$" VarName TypeDeclaration?             -->
  <!--             (":=" ExprSingle)? )*                      -->
  <xsd:complexType name="blockVarDecl">
      <xsd:sequence minOccurs="1" maxOccurs="unbounded">
        <xsd:element name="varName" type="xqx:QName"/>
        <xsd:element ref="xqx:typeDeclaration" minOccurs="0"/>
        <xsd:element name="varValue" type="xqx:exprWrapper"
                     minOccurs="0"/>
      </xsd:sequence>
  </xsd:complexType>

  <xsd:element name="blockVarDecl" type="xqxsx:blockVarDecl"/>

  <!-- Block (3 of 3):                                        -->
  <!--   BlockBody ::= (Expr ";")*                            -->
  <xsd:complexType name="blockBody">
    <xsd:sequence>
      <xsd:element name="blockExpr" type="xqx:exprWrapper"
                   minOccurs="1" maxOccurs="unbounded"/>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:element name="blockBody" type="xqxsx:blockBody"/>


  <!-- ExitExpr:                                       -->
  <!--   ExitExpr ::= "exit" "with" ExprSingle      -->
  <xsd:element name="exitExpr" type="xqxsx:expr"
               substitutionGroup="xqxsx:expr"/>


  <!-- WhileExpr:                                             -->
  <!--   WhileExpr ::= "while" "(" ExprSingle ")" Block       -->
  <xsd:complexType name="whileExpr">
    <xsd:complexContent>
      <xsd:extension base="xqxsx:expr">
        <xsd:sequence>
          <xsd:element name="whileTest" type="xqx:exprWrapper"/>
          <xsd:element ref="xqxsx:block"/>
        </xsd:sequence>
      </xsd:extension>
    </xsd:complexContent>
  </xsd:complexType>

  <xsd:element name="whileExpr" type="xqxsx:whileExpr"
               substitutionGroup="xqxsx:expr"/>


  <!-- ContinueExpr:                                          -->
  <!--   ContinueExpr ::= "continue" "loop"                   -->
  <xsd:complexType name="continueExpr">
    <xsd:complexContent>
      <xsd:restriction base="xqxsx:expr"/>
    </xsd:complexContent>
  </xsd:complexType>

  <xsd:element name="continueExpr" type="xqxsx:continueExpr"
               substitutionGroup="xqxsx:expr"/>


  <!-- BreakExpr:                                             -->
  <!--   BreakExpr ::= "break" "loop"                         -->
  <xsd:complexType name="breakExpr">
    <xsd:complexContent>
      <xsd:restriction base="xqxsx:expr"/>
    </xsd:complexContent>
  </xsd:complexType>

  <xsd:element name="breakExpr" type="xqxsx:breakExpr"
               substitutionGroup="xqxsx:expr"/>

</xsd:schema>



<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                    xmlns="http://www.w3.org/2005/XQueryX"
                    targetNamespace="http://www.w3.org/2005/XQueryX"
                    elementFormDefault="qualified" attributeFormDefault="qualified">

<!-- Redefine one or more components of the XQueryX XML Schema -->
<!-- The redefinition starts with XQuery Update Facility 1.0   -->
<!--   XQueryX instead of XQueryX 1.0                          -->
<xsd:redefine schemaLocation="http://www.w3.org/2007/xquery-update-10/xquery-update-10-xqueryx-redef.xsd">

<!-- Redefine the functionDecl complex type -->
  <xsd:complexType name="functionDecl">
    <xsd:complexContent>
      <xsd:extension base="functionDecl">
        <xsd:attribute name="simpleFunction"
                       type="xsd:boolean" default="true"/>
        <xsd:attribute name="sequentialFunction"
                       type="xsd:boolean" default="false"/>
      </xsd:extension>
    </xsd:complexContent>
  </xsd:complexType>

</xsd:redefine>

</xsd:schema>

B.2 Stylesheet

This section specifies the XSLT stylesheet that defines the semantics of XQueryX in support of XQuery Scripting Extension 1.0. It imports the XSLT stylesheet defined in [XQuery Update Facility], and provides additional templates that define the semantics of the XQueryX representation of XQuery Scripting Extension 1.0 by transforming that XQueryX representation into the human readable syntax of XQuery Scripting Extension 1.0. A copy of this stylesheet is located at http://www.w3.org/2008/xquery-sx-10/xquery-sx-10-xqueryx.xsl. Please note that the content of this stylesheet is subject to change at any time before this document is published as a Recommendation.


<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xqx="http://www.w3.org/2005/XQueryX"
                xmlns:xqxuf="http://www.w3.org/2007/xquery-update-10"
                xmlns:xqxsx="http://www.w3.org/2008/xquery-sx-10">

<!-- Initial creation                  2008-03-01: Jim Melton -->

<xsl:import href="http://www.w3.org/2007/xquery-update-10/xquery-update-10-xqueryx.xsl"/>


<!-- constDecl                                                -->
<xsl:template match="xqxsx:constDecl">
  <xsl:value-of select="$NEWLINE"/>
  <xsl:text>declare constant </xsl:text>
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="xqxsx:constName">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="xqxsx:constValue">
  <xsl:apply-templates/>
</xsl:template>


<!-- assignmentExpr                                           -->
<xsl:template match="xqxsx:assignmentExpr">
  <xsl:value-of select="$NEWLINE"/>
  <xsl:text>set </xsl:text>
  <xsl:apply-templates select="xqx:positionalVariableBinding"/>
  <xsl:text> := </xsl:text>
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="xqxsx:assignedExpr">
  <xsl:apply-templates/>
</xsl:template>


<!-- block                                                    -->
<xsl:template match="xqxsx:block">
  <xsl:value-of select="$NEWLINE"/>
  <xsl:value-of select="$LBRACE"/>
  <xsl:value-of select="$SPACE"/>
  <xsl:apply-templates/>
  <xsl:value-of select="$SPACE"/>
  <xsl:value-of select="$RBRACE"/>
  <xsl:value-of select="$SPACE"/>
</xsl:template>

<!-- blockVarDecl                                             -->
<xsl:template match="xqxsx:blockVarDecl[position()=1 and position()=last()]">
  <xsl:text>declare </xsl:text>
  <xsl:apply-templates select="xqxsx:varName"/>
  <xsl:if test="xqx:typeDeclaration">
    <xsl:apply-templates select="xqx:typeDeclaration"/>
  </xsl:if>
  <xsl:if test="xqxsx:varValue">
    <xsl:text> := </xsl:text>
    <xsl:apply-templates select="xqxsx:varValue"/>
  </xsl:if>
  <xsl:value-of select="$SEMICOLON"/>
</xsl:template>

<xsl:template match="xqxsx:blockVarDecl[position()=1 and position()!=last()]">
  <xsl:text>declare </xsl:text>
  <xsl:apply-templates select="xqxsx:varName"/>
  <xsl:if test="xqx:typeDeclaration">
    <xsl:apply-templates select="xqx:typeDeclaration"/>
  </xsl:if>
  <xsl:if test="xqxsx:varValue">
    <xsl:text> := </xsl:text>
    <xsl:apply-templates select="xqxsx:varValue"/>
  </xsl:if>
</xsl:template>

<xsl:template match="xqxsx:blockVarDecl[position()>1 and position()&lt;last()]">
  <xsl:value-of select="$COMMA"/>
  <xsl:value-of select="$NEWLINE"/>
  <xsl:apply-templates select="xqxsx:varName"/>
  <xsl:if test="xqx:typeDeclaration">
    <xsl:apply-templates select="xqx:typeDeclaration"/>
  </xsl:if>
  <xsl:if test="xqxsx:varValue">
    <xsl:text> := </xsl:text>
    <xsl:apply-templates select="xqxsx:varValue"/>
  </xsl:if>
</xsl:template>

<xsl:template match="xqxsx:blockVarDecl[position()>1 and position()=last()]">
  <xsl:value-of select="$COMMA"/>
  <xsl:value-of select="$NEWLINE"/>
  <xsl:apply-templates select="xqxsx:varName"/>
  <xsl:if test="xqx:typeDeclaration">
    <xsl:apply-templates select="xqx:typeDeclaration"/>
  </xsl:if>
  <xsl:if test="xqxsx:varValue">
    <xsl:text> := </xsl:text>
    <xsl:apply-templates select="xqxsx:varValue"/>
  </xsl:if>
  <xsl:value-of select="$SEMICOLON"/>
</xsl:template>

<xsl:template match="xqxsx:varName">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="xqxsx:varValue">
  <xsl:apply-templates/>
</xsl:template>

<!-- blockBody                                                -->
<xsl:template match="xqxsx:blockBody">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="xqxsx:blockExpr">
  <xsl:apply-templates/>
  <xsl:value-of select="$SEMICOLON"/>
</xsl:template>


<!-- exitExpr                                          -->
<xsl:template match="xqxsx:exitExpr">
  <xsl:value-of select="$NEWLINE"/>
  <xsl:text>exit with </xsl:text>
  <xsl:apply-templates/>
</xsl:template>


<!-- whileExpr                                                -->
<xsl:template match="xqxsx:whileExpr">
  <xsl:value-of select="$NEWLINE"/>
  <xsl:text>while </xsl:text>
  <xsl:value-of select="$LPAREN"/>
  <xsl:value-of select="$SPACE"/>
  <xsl:apply-templates select="xqxsx:whileTest"/>
  <xsl:value-of select="$SPACE"/>
  <xsl:value-of select="$RPAREN"/>
  <xsl:value-of select="$NEWLINE"/>
  <xsl:apply-templates select="xqxsx:block"/>
  <xsl:value-of select="$NEWLINE"/>
</xsl:template>

<xsl:template match="xqxsx:whileTest">
  <xsl:apply-templates/>
</xsl:template>


<!-- continueExpr                                             -->
<xsl:template match="xqxsx:continueExpr">
  <xsl:value-of select="$NEWLINE"/>
  <xsl:text>continue loop </xsl:text>
</xsl:template>


<!-- breakExpr                                                -->
<xsl:template match="xqxsx:breakExpr">
  <xsl:value-of select="$NEWLINE"/>
  <xsl:text>break loop </xsl:text>
</xsl:template>


<!-- Over-ride the template for functionDecl in XQuery        -->
<!--   Update Facility xquery-update-10-xqueryx-redef.xsd     -->
  <xsl:template match="xqx:functionDecl" priority="200">
    <xsl:text>declare </xsl:text>
    <xsl:choose>
      <xsl:when test="@xqx:updatingFunction and
                      @xqx:updatingFunction = 'true'">
        <xsl:text>updating </xsl:text>
      </xsl:when>
      <xsl:when test="@xqx:sequentialFunction and
                      @xqx:sequentialFunction = 'true'">
        <xsl:text>sequential </xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:text>simple </xsl:text>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:text>function </xsl:text>
    <xsl:apply-templates select="xqx:functionName"/>
    <xsl:apply-templates select="xqx:paramList"/>
    <xsl:apply-templates select="xqx:typeDeclaration"/>
    <xsl:apply-templates select="xqx:functionBody"/>
    <xsl:if test="xqx:externalDefinition">
      <xsl:text> external </xsl:text>
    </xsl:if>
  </xsl:template>



</xsl:stylesheet>

B.3 Example

The following example is based on the data and queries in the use cases in [XQuery Scripting Use Cases]. In this example, we show the English description of the query, the XQuery Scripting Extension solution given in [XQuery Scripting Use Cases], an XQueryX solution, and the XQuery Update Facility expression that results from applying the Update Facility XQueryX-to-XQuery Update Facility transformation defined by the stylesheet in B.2 Stylesheet to the Scripting Extension XQueryX solution. The XQuery Scripting Extension expression that is produced is presented only as a sanity-check—the intent of the stylesheet is not to recreate the original XQuery expression, but to produce a valid XQuery expression with the same semantics. The semantics of the Scripting Extension XQueryX solution are determined by the semantics of the XQuery Update Facility expression that results from that transformation. The "correctness" of that transformation is determined by asking the following the question: Can some Scripting Extension XQueryX processor QX process some Scripting Extension XQueryX document D1 to produce results R1, after which the stylesheet is used to translate D1 into an XQuery Scripting Extension expression E1 that, when processed by some XQuery Scripting Extension processor Q, produces results R2 that are equivalent (under some meaningful definition of "equivalent") to results R1?

Comparison of the results of the Scripting Extension XQueryX-to-XQuery Scripting Extension transformation given in this document with the XQuery Scripting Extension solutions in [XQuery Scripting Use Cases] may be helpful in evaluating the correctness of the Update Facility XQueryX solution in each example.

The XQuery Scripting Extension Use Cases solution given for each example is provided only to assist readers of this document in understanding the Scripting Extension XQueryX solution. There is no intent to imply that this document specifies a "compilation" or "transformation" of XQuery Scripting Extension syntax into Scripting Extension XQueryX syntax.

In the following example, note that path expressions are expanded to show their structure. Also, note that the prefix syntax for binary operators like "and" makes the precedence explicit. In general, humans find it easier to read an XML representation that does not expand path expressions, but it is less convenient for programmatic representation and manipulation. XQueryX is designed as a language that is convenient for production and modification by software, and not as a convenient syntax for humans to read and write.

Finally, please note that white space, including new lines, have been added to some of the Scripting Extension XQueryX documents and XQuery Scripting Extension expressions for readability. That additional white space is not produced by the Scripting Extension XQueryX-to-XQuery Scripting Extension transformation.

This example is based on query "Q2" from [XQuery Scripting Use Cases], use case "R": "Scripting Relational Data":

B.3.1 XQuery Representation

let $uid := doc("users.xml")/users/user_tuple[name = "Roger Smith"]/userid
let $topbid := max(doc("bids.xml")/bids/bid_tuple[itemno = 1007]/bid)
let $newbid := $topbid * 1.1
return
  if($newbid <= 240) then {
    insert nodes
      <bid_tuple>
        <userid>{ data($uid) }</userid>
        <itemno>1002</itemno>
        <bid>{ $newbid }</bid>
        <bid_date>1999-03-03</bid_date>
      </bid_tuple>
    into doc("bids.xml")/bids;
    exit with <new_bid>{ $newbid }</new_bid>;
  } else {
    exit with <top_bid>{ $topbid }</top_bid>;
  }

B.3.2 XQueryX Representation

<!--
let $uid := doc("users.xml")/users/user_tuple[name = "Roger Smith"]/userid
let $topbid := max(doc("bids.xml")/bids/bid_tuple[itemno = 1007]/bid)
let $newbid := $topbid * 1.1
return
  if($newbid <= 240) then {
    insert nodes
      <bid_tuple>
        <userid>{ data($uid) }</userid>
        <itemno>1002</itemno>
        <bid>{ $newbid }</bid>
        <bid_date>1999-03-03</bid_date>
      </bid_tuple>
    into doc("bids.xml")/bids;
    exit with <new_bid>{ $newbid }</new_bid>;
  } else {
    exit with <top_bid>{ $topbid }</top_bid>;
  }
-->
<xqx:module xmlns:xqx="http://www.w3.org/2005/XQueryX"
            xmlns:xqxuf="http://www.w3.org/2007/xquery-update-10"
            xmlns:xqxsx="http://www.w3.org/2008/xquery-sx-10"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://www.w3.org/2005/XQueryX
                                http://www.w3.org/2005/XQueryX/xqueryx.xsd
                                http://www.w3.org/2007/xquery-update-10                            
http://www.w3.org/2007/xquery-update-10/xquery-update-10-xqueryx.xsd
                                http://www.w3.org/2008/xquery-sx-10                            
http://www.w3.org/2008/xquery-sx-10/xquery-sx-10-xqueryx.xsd">

    <xqx:queryBody>
      <xqx:flworExpr>
<!-- let $uid := doc("users.xml")/users/user_tuple[name = "Roger Smith"]/userid -->
        <xqx:letClause>
          <xqx:letClauseItem>
            <xqx:typedVariableBinding>
              <xqx:varName>uid</xqx:varName>
            </xqx:typedVariableBinding>
            <xqx:letExpr>
              <xqx:pathExpr>
                <xqx:stepExpr>
                  <xqx:filterExpr>
                    <xqx:functionCallExpr>
                      <xqx:functionName
                        xqx:prefix="fn">doc</xqx:functionName>
                      <xqx:arguments>
                        <xqx:stringConstantExpr>
                          <xqx:value>users.xml</xqx:value>
                        </xqx:stringConstantExpr>
                      </xqx:arguments>
                    </xqx:functionCallExpr>
                  </xqx:filterExpr>
                </xqx:stepExpr>
                <xqx:stepExpr>
                  <xqx:xpathAxis>child</xqx:xpathAxis>
                  <xqx:nameTest>users</xqx:nameTest>
                </xqx:stepExpr>
                <xqx:stepExpr>
                  <xqx:xpathAxis>child</xqx:xpathAxis>
                  <xqx:nameTest>user-tuple</xqx:nameTest>
                  <xqx:predicates>
                    <xqx:equalOp>
                      <xqx:firstOperand>
                        <xqx:pathExpr>
                          <xqx:stepExpr>
                            <xqx:xpathAxis>child</xqx:xpathAxis>
                            <xqx:nameTest>name</xqx:nameTest>
                          </xqx:stepExpr>
                        </xqx:pathExpr>
                      </xqx:firstOperand>
                      <xqx:secondOperand>
                        <xqx:stringConstantExpr>
                          <xqx:value>Roger Smith</xqx:value>
                        </xqx:stringConstantExpr>
                      </xqx:secondOperand>
                    </xqx:equalOp>
                  </xqx:predicates>
                </xqx:stepExpr>
                <xqx:stepExpr>
                  <xqx:xpathAxis>child</xqx:xpathAxis>
                  <xqx:nameTest>userid</xqx:nameTest>
                </xqx:stepExpr>
              </xqx:pathExpr>
            </xqx:letExpr>
          </xqx:letClauseItem>
        </xqx:letClause>
<!-- let $topbid := max(doc("bids.xml")/bids/bid_tuple[itemno = 1007]/bid) -->
        <xqx:letClause>
          <xqx:letClauseItem>
            <xqx:typedVariableBinding>
              <xqx:varName>topbid</xqx:varName>
            </xqx:typedVariableBinding>
            <xqx:letExpr>
              <xqx:pathExpr>
                <xqx:stepExpr>
                  <xqx:filterExpr>
                    <xqx:functionCallExpr>
                      <xqx:functionName
                        xqx:prefix="fn">max</xqx:functionName>
                      <xqx:arguments>
                        <xqx:pathExpr>
                          <xqx:stepExpr>
                            <xqx:filterExpr>
                              <xqx:functionCallExpr>
                                <xqx:functionName
                                  xqx:prefix="fn">doc</xqx:functionName>
                                <xqx:arguments>
                                  <xqx:stringConstantExpr>
                                    <xqx:value>bids.xml</xqx:value>
                                  </xqx:stringConstantExpr>
                                </xqx:arguments>
                              </xqx:functionCallExpr>
                            </xqx:filterExpr>
                          </xqx:stepExpr>
                          <xqx:stepExpr>
                            <xqx:xpathAxis>child</xqx:xpathAxis>
                            <xqx:nameTest>bids</xqx:nameTest>
                          </xqx:stepExpr>
                          <xqx:stepExpr>
                            <xqx:xpathAxis>child</xqx:xpathAxis>
                            <xqx:nameTest>bid-tuple</xqx:nameTest>
                            <xqx:predicates>
                              <xqx:equalOp>
                                <xqx:firstOperand>
                                  <xqx:pathExpr>
                                    <xqx:stepExpr>
                                      <xqx:xpathAxis>child</xqx:xpathAxis>
                                      <xqx:nameTest>itemno</xqx:nameTest>
                                    </xqx:stepExpr>
                                  </xqx:pathExpr>
                                </xqx:firstOperand>
                                <xqx:secondOperand>
                                  <xqx:integerConstantExpr>
                                    <xqx:value>1007</xqx:value>
                                  </xqx:integerConstantExpr>
                                </xqx:secondOperand>
                              </xqx:equalOp>
                            </xqx:predicates>
                          </xqx:stepExpr>
                          <xqx:stepExpr>
                            <xqx:xpathAxis>child</xqx:xpathAxis>
                            <xqx:nameTest>bid</xqx:nameTest>
                          </xqx:stepExpr>
                        </xqx:pathExpr>
                      </xqx:arguments>
                    </xqx:functionCallExpr>
                  </xqx:filterExpr>
                </xqx:stepExpr>
              </xqx:pathExpr>
            </xqx:letExpr>
          </xqx:letClauseItem>
        </xqx:letClause>
<!-- let $newbid := $topbid * 1.1 -->
        <xqx:letClause>
          <xqx:letClauseItem>
            <xqx:typedVariableBinding>
              <xqx:varName>newbid</xqx:varName>
            </xqx:typedVariableBinding>
            <xqx:letExpr>
              <xqx:multiplyOp>
                <xqx:firstOperand>
                  <xqx:varRef>
                    <xqx:name>topbid</xqx:name>
                  </xqx:varRef>
                </xqx:firstOperand>
                <xqx:secondOperand>
                  <xqx:decimalConstantExpr>
                    <xqx:value>1.1</xqx:value>
                  </xqx:decimalConstantExpr>
                </xqx:secondOperand>
              </xqx:multiplyOp>
            </xqx:letExpr>
          </xqx:letClauseItem>
        </xqx:letClause>
<!-- return -->
        <xqx:returnClause>
<!--   if($newbid <= 240)        -->
          <xqx:ifThenElseExpr>
            <xqx:ifClause>
              <xqx:lessThanOrEqualOp>
                <xqx:firstOperand>
                  <xqx:varRef>
                    <xqx:name>newbid</xqx:name>
                  </xqx:varRef>
                </xqx:firstOperand>
                <xqx:secondOperand>
                  <xqx:integerConstantExpr>
                    <xqx:value>240</xqx:value>
                  </xqx:integerConstantExpr>
                </xqx:secondOperand>
              </xqx:lessThanOrEqualOp>
            </xqx:ifClause>
<!--                      then { -->
            <xqx:thenClause>
              <xqxsx:block>
                <xqxsx:blockBody>
                  <xqxsx:blockExpr>
<!--     insert nodes -->
                    <xqxuf:insertExpr>
                      <xqxuf:sourceExpr>
<!--       <bid_tuple> -->
                        <xqx:elementConstructor>
                          <xqx:tagName>bid_tuple</xqx:tagName>
                          <xqx:elementContent>
<!--         <userid>{ data($uid) }</userid> -->
                            <xqx:elementConstructor>
                              <xqx:tagName>userid</xqx:tagName>
                              <xqx:elementContent>
                                <xqx:functionCallExpr>
                                  <xqx:functionName
                                    xqx:prefix="fn">data</xqx:functionName>
                                  <xqx:arguments>
                                    <xqx:exprList>
                                      <xqx:expr>
                                        <xqx:varRef>
                                          <xqx:name>uid</xqx:name>
                                        </xqx:varRef>
                                      </xqx:expr>
                                    </xqx:exprList>
                                  </xqx:arguments>
                                </xqx:functionCallExpr>
                              </xqx:elementContent>
                            </xqx:elementConstructor>
<!--         <itemno>1002</itemno> -->
                            <xqx:elementConstructor>
                              <xqx:tagName>itemno</xqx:tagName>
                              <xqx:elementContent>
                                <xqx:integerConstantExpr>
                                  <xqx:value>1002</xqx:value>
                                </xqx:integerConstantExpr>
                              </xqx:elementContent>
                            </xqx:elementConstructor>
<!--         <bid>{ $newbid }</bid> -->
                            <xqx:elementConstructor>
                              <xqx:tagName>bid</xqx:tagName>
                              <xqx:elementContent>
                                <xqx:varRef>
                                  <xqx:name>bid</xqx:name>
                                </xqx:varRef>
                              </xqx:elementContent>
                            </xqx:elementConstructor>
<!--         <bid_date>1999-03-03</bid_date> -->
                            <xqx:elementConstructor>
                              <xqx:tagName>bid_date</xqx:tagName>
                              <xqx:elementContent>
                                <xqx:stringConstantExpr>
                                  <xqx:value>1999-03-03</xqx:value>
                                </xqx:stringConstantExpr>
                              </xqx:elementContent>
                            </xqx:elementConstructor>
                          </xqx:elementContent>
                        </xqx:elementConstructor>
                      </xqxuf:sourceExpr>
<!--     into doc("bids.xml")/bids; -->
                      <xqxuf:insertInto/>
                      <xqxuf:targetExpr>
                        <xqx:pathExpr>
                          <xqx:stepExpr>
                            <xqx:filterExpr>
                              <xqx:functionCallExpr>
                                <xqx:functionName
                                  xqx:prefix="fn">doc</xqx:functionName>
                                <xqx:arguments>
                                  <xqx:stringConstantExpr>
                                    <xqx:value>bids.xml</xqx:value>
                                  </xqx:stringConstantExpr>
                                </xqx:arguments>
                              </xqx:functionCallExpr>
                            </xqx:filterExpr>
                          </xqx:stepExpr>
                          <xqx:stepExpr>
                            <xqx:xpathAxis>child</xqx:xpathAxis>
                            <xqx:nameTest>bids</xqx:nameTest>
                          </xqx:stepExpr>
                        </xqx:pathExpr>
                      </xqxuf:targetExpr>
                    </xqxuf:insertExpr>
                  </xqxsx:blockExpr>
<!--     exit with <new_bid>{ $newbid }</new_bid>; -->
                  <xqxsx:blockExpr>
                    <xqxsx:exitExpr>
                      <xqx:elementConstructor>
                        <xqx:tagName>new_bid</xqx:tagName>
                        <xqx:elementContent>
                          <xqx:varRef>
                            <xqx:name>newbid</xqx:name>
                          </xqx:varRef>
                        </xqx:elementContent>
                      </xqx:elementConstructor>
                    </xqxsx:exitExpr>
                  </xqxsx:blockExpr>
                  <xqxsx:termSemicolon/>
                </xqxsx:blockBody>
              </xqxsx:block>
            </xqx:thenClause>
<!--   } else { -->
            <xqx:elseClause>
<!--     exit with <top_bid>{ $topbid }</top_bid>; -->
              <xqxsx:block>
                <xqxsx:blockBody>
                  <xqxsx:blockExpr>
                    <xqxsx:exitExpr>
                      <xqx:elementConstructor>
                        <xqx:tagName>top_bid</xqx:tagName>
                        <xqx:elementContent>
                          <xqx:varRef>
                            <xqx:name>topbid</xqx:name>
                          </xqx:varRef>
                        </xqx:elementContent>
                      </xqx:elementConstructor>
                    </xqxsx:exitExpr>
                  </xqxsx:blockExpr>
                  <xqxsx:termSemicolon/>
                </xqxsx:blockBody>
              </xqxsx:block>
            </xqx:elseClause>
          </xqx:ifThenElseExpr>
        </xqx:returnClause>
<!-- } -->
      </xqx:flworExpr>
    </xqx:queryBody>
</xqx:module>

B.3.3 Transformed XQuery Representation

Application of the stylesheet in B.2 Stylesheet to the Update Facility XQueryX representation results in the following XQuery representation:

( let $uid:=fn:doc("users.xml")/child::users/
      child::user-tuple[(child::name = "Roger Smith")]/child::userid
  let $topbid:=fn:max(fn:doc("bids.xml")/child::bids/
      child::bid-tuple[(child::itemno = 1007)]/child::bid)
  let $newbid:=($topbid*1.1)
  return
    ( if (($newbid <= 240)) then 
      { insert nodes
          <bid_tuple><userid>{fn:data($uid)}</userid>
          <itemno>{1002}</itemno>
          <bid>{$bid}</bid>
          <bid_date>{"1999-03-03"}</bid_date></bid_tuple>
        into 
          fn:doc("bids.xml")/child::bids;
        exit with <new_bid>{$newbid}</new_bid>; }  else 
      { exit with <top_bid>{$topbid}</top_bid>; } )
)

C Implementation-Defined Items

The following items in this specification are implementation-defined:

  1. The effects of snapshot semantics on persistent storage. For example, it is implementation-defined whether the effects of an fn:put function are visible to an fn:doc, fn:doc-available, or fn:collection function executed in a subsequent snapshot.

  2. The mechanism (if any) by which the XQuery environment exchanges parameters and results with an external function.

D References

XQuery 1.0
XQuery 1.0: An XML Query Language, W3C Recommendation, 23 January 2007.
XML Syntax for XQuery 1.0
XML Syntax for XQuery 1.0, W3C Recommendation, 23 January 2007.
XQuery Data Model
XQuery 1.0 and XPath 2.0 Data Model (XDM), W3C Recommendation, 23 January 2007.
XQuery Update Facility
XQuery Update Facility 1.0, W3C Candidate Recommendation, March 2008.
XQuery Scripting Requirements
XQuery Scripting Extension 1.0 Requirements, W3C Working Draft, 23 March 2007.
XQuery Scripting Use Cases
XQuery Scripting Extension 1.0 Use Cases, W3C Working Draft 23 March 2007.

E Issues

The following are some issues that are under discussion in the working group:

  1. Semantics of break and continue:

    Break and continue expressions are currently defined to affect the nearest enclosing while-loop. Alternatively, they could be defined to affect the nearest enclosing FLWOR or while-loop.

    If break and continue expressions were defined to affect FLWOR expressions, the semantics of FLWOR would become more complex. Currently, the return-clause values for all iterations are concatenated to form the result of a FLWOR. If an iteration is terminated by a break or continue, we would need to define which XDM values from that iteration are retained as part of the FLWOR-result, and which of the side-effects from that iteration are made effective. For example:

    • Should this example return ("a", "a") or ()?

      for $i in (1, 2)
      return ("a", continue loop)
      
    • Suppose the initial value of $x is 0. What is the final value of $x after each of the following examples?

      for $i in (1, 2)
      return set $x := ($i, break loop)
      
      for $i in (1, 2)
      return (set $x := $i, break loop)
      
      for $i in (1, 2)
      return {set $x := $i; break loop;}
      
    • What is the value of the following expression?

      for $i in (1, 2, 3, 4)
      return
         ($i, if ($i < 3) then continue loop else break loop)
      
    • Suppose the initial value of $list is (). What is the final value of $list after each of the following examples?

      for $i in (1, 2, 3, 4)
      return {
         $list := ($list, $i);
         if ($i < 3) then continue loop else break loop;
      }
      
      set $list :=
         for $i in (1, 2, 3, 4)
         return
            ($i, if ($i < 3) then continue loop else break loop)
      

    At present, the working group has defined break and continue expressions to affect while-loops only. The semantics of while are more straightforward than those of FLWOR because the body of a while-expression is a block, which does not return a value; therefore the issue of how to handle "partial iterations" does not arise.

  2. Explicit declaration of simple functions:

    Some functions that contain sequential expressions nevertheless have no externally visible side effects. For example, if the Fibonacci block in 2.3.4 While Expression were the body of a function, the function would have no externally visible side effects. Should it be possible for a user to declare such a function to be simple? Then it could be used (for example) in the for-clause of a FLWOR to iterate over Fibonacci numbers.

    The following issues have been discussed:

    1. We would need to trust the user's declaration, and an incorrect declaration might lead to unpredictable results.

    2. There are grammar problems because the body of a simple function is an enclosed expression, while the body of a sequential function is a block. These are not syntactically distinguishable with finite look-ahead, but they are not identical because an enclosed expression does not end with a semicolon. The following approaches to deal with this grammar problem have been considered:

      1. If a function is declared with no category, it takes an enclosed expression as its body and it is implicitly a simple function. If a function is explicitly declared "simple", it takes a block as its body (then its result is defined by an "exit" expression.)

      2. A simple function that contains a sequential expression must have double {{curly braces}} around its body: the outer { } denote an enclosed expression and the inner { } denote a block.

      3. Invent a new declaration like "programmed simple" to denote a simple function whose body is a block.

      4. Change the definition of a block so that, if its final expression has no semicolon, the value of that expression is returned as the value of the block. Then let the body of a simple function be a block instead of an enclosed expression. This approach leads to some new questions: What happens if the body of a while-loop returns a value? Should semicolons be allowed outside blocks? Do we still need an "exit" expression? Etc.

  3. Role of semicolon:

    The current specification uses semicolons only inside blocks, to terminate each expression in the block. This corresponds to the use of semicolons in traditional programming languages such as Java. Alternatively, we could define a semicolon as a binary operator that evaluates its left operand expression, applies any resulting PUL, and then evaluates its right operand expression. The resulting "semicolon expression" could appear either inside or outside a block. In this approach, a semicolon might be thought of as an "apply updates" operator. This nontraditional use of a familiar operator might be confusing, and would not increase the expressive power of the language.

  4. Mixing XDM with PUL:

    In the current specification, no expression may return both a non-empty XDM instance and a non-empty pending update list. Should this restriction be removed? If so, we would no longer need the category "vacuous expression." The contexts currently requiring an updating or vacuous expression would be changed to require an updating or simple expression. In general, the category rules would be relaxed to permit mixing of updating and simple expressions.

  5. Passing nodes to functions:

    We need to specify the semantics of passing nodes to functions. Presumably the function can modify the value of a node that is passed to it, and this side effect is seen by the caller. But presumably a function cannot modify the binding of a variable in the calling environment. For example, if the caller invokes a sequential function f($x), then $x is still bound to the same nodeid after the function call, even if the function has deleted the node or modified its content.