This appendix provides an EBNF grammar for the XQuery language. This grammar differs from the official one printed in the standard only in presentation (for example, some names have been changed and some productions cleaned up to make the grammar easier to read).
XQuery borrows two definitions from the XML 1.0 and XML Names specifications: Char
and NCName
. Because these definitions involve large character tables, I didn't include them here but instead refer you to the URLs in the grammar below.
The XQuery grammar requires that characters be recognized and parsed differently in certain contexts (i.e., a context-sensitive lexer). For example, within element or attribute content, characters are parsed differently than outside it. XQuery also requires that whitespace be handled differently in some contexts.
In general, XQuery requires three characters of lookahead to handle expressions like XML comments, XQuery pragmas, and CDATA sections. XQuery often requires one or two tokens of lookahead to disambiguate production choices.
Expressions on the left consist of the productions on the right of the ::=
symbol. Quoted strings and regular expression character ranges indicate literal text. The EBNF symbols *
, +
, ?
, |
, and ()
are used with their usual meanings (zero or more, one or more, zero or one, choice, and group, respectively).
Example E.1. The XQuery grammar
Module ::= Version? (Main | Library) Main ::= Prolog QueryBody Library ::= ModuleDecl Prolog ModuleDecl ::= "module" namespace prefix "=" String ";" Prolog ::= ((BaseURIDecl | CollationDecl | DefaultNsDecl | FunctionDecl | ModuleImport | NamespaceDecl | SchemaImport | ValidationDecl | VarDecl | XMLSpaceDecl) ";")* Version ::= "xquery" "version" String ";" BaseURIDecl ::= "declare" "base-uri" StringLiteral CollationDecl ::= "declare" "default" "collation" "=" String DefaultNsDecl ::= "declare" "default" ("element" | "function") "namespace" "=" String FunctionDecl ::= "declare" "function" QName "(" ParamList? ")" ("as" SequenceType)? (EnclosedExpr | "external") ParamList ::= Param ("," Param)* Param ::= Variable TypeDecl? ModuleImport ::= "import" "module" ("namespace" NCName "=")? String ("at" String)? NamespaceDecl ::= "declare" "namespace" NCName "=" String ValidationDecl ::= "declare" "validation" ("lax" | "strict" | "skip") VarDecl ::= "declare" S "variable" Variable TypeDecl? ((EnclosedExpr) | "external") XMLSpaceDecl ::= "declare" "xmlspace" "=" ("preserve" | "strip") QueryBody ::= Expr Expr ::= ExprSingle ("," ExprSingle)* ExprSingle ::= FLWOR | Quantified | Typeswitch | Conditional | Disjunction FLWOR ::= (For | Let)+ Where? OrderBy? Return For ::= "for" ForDecl ("," ForDecl)* ForDecl ::= Variable TypeDecl? PositionVar? "in" ExprSingle PositionVar ::= "at" Variable Let ::= "let" LetDecl ("," LetDecl)* LetDecl ::= Variable TypeDecl? ":=" ExprSingle Where ::= "where" Expr OrderBy ::= "stable"? "order" "by" OrderByList OrderByList ::= OrderSpec ("," OrderSpec)* OrderSpec ::= ExprSingle OrderModifier OrderModifier ::= ("ascending" | "descending")? ("empty" ("greatest" | "least"))? ("collation" String)? Return ::= "return" ExprSingle Quantified ::= ("some" | "every") QuantList "satisfies" ExprSingle QuantList ::= QuantDecl ("," QuantDecl)* QuantDecl ::= Variable TypeDecl? "in" ExprSingle Typeswitch ::= "typeswitch" "(" Expr ")" CaseClause+ "default" Variable? "return" ExprSingle CaseClause ::= "case" (Variable "as")? SequenceType "return" ExprSingle Conditional ::= "if" "(" Expr ")" "then" Expr "else" ExprSingle Disjunction ::= Conjunction ( "or" Conjunction )* Conjunction ::= InstanceOf ( "and" InstanceOf )* InstanceOf ::= TreatAs ( "instance" "of" SequenceType )? TreatAs ::= CastableAs ( "treat" "as" SequenceType )? CastableAs ::= CastAs ( "castable" "as" SingleType )? CastAs ::= Comparison ( "cast" "as" SingleType )? Comparison ::= Range ( CompOp Range)? CompOp ::= ValueComp | GeneralComp | NodeComp | OrderComp ValueComp ::= "eq" | "ne" | "lt" | "le" | "gt" | "ge" GeneralComp ::= "=" | "!=" | "<" | "<=" | ">" | ">=" NodeComp ::= "is" OrderComp ::= "<<" | ">>" Range ::= Addition ( "to" Addition )? Addition ::= Multiplication ( ("+" | "-") Multiplication )* Multiplication ::= Unary ( ("*" | "div" | "idiv" | "mod") Unary )* Unary ::= ("-" | "+")* Union Union ::= Set ( ("union" | "|") Set )* Set ::= Value ( ("intersect" | "except") Value )* Value ::= Validation | Path Path ::= ("/" RelativePath?) | ("//" RelativePath) | RelativePath RelativePath ::= StepExpr (("/" | "//") StepExpr)* StepExpr ::= AxisStep | FilterStep AxisStep ::= Step Predicate* FilterStep ::= PrimaryExpr Predicate* Step ::= Axis "::" NodeTest | AbbrStep AbbrStep ::= "." | ".." | "@" NameTest | NodeTest Axis ::= "ancestor" | "ancestor-or-self" | "attribute" | "child" | "descendant-or-self" | "descendant" | "following" | "following-sibling" | "parent" | "preceding" | "preceding-sibling" | "self" NodeTest ::= KindTest | NameTest NameTest ::= QName | Wildcard Wildcard ::= (NCName ":")? "*" | "*" ":" NCName PrimaryExpr ::= Literal | FunctionCall | Variable | "(" Expr? ")" | Ctor Predicate ::= "[" Expr "]" Validation ::= "validate" SchemaMode? SchemaContxt? EnclosedExpr SchemaContxt ::= "context" SchemaCtxtLoc | "global" Ctor ::= ElementCtor | XmlComment | XmlPI | CdataSection | CompDocCtor | CompElemCtor | CompAttrCtor | CompTextCtor | CompNsCtor | CompCommentCtor | CompPiCtor Literal ::= Number | String Number ::= Integer | Decimal | Double FunctionCall ::= QName "(" Expr? ")" ElementCtor ::= "<" QName AttrList ("/>" | (">" ElemContent* "</" QName S? ">")) XmlComment ::= "<!—" Char* "—>" XmlPI ::= "<?" NCName Char* "?>" CdataSection ::= "<![CDATA[" Char* "]]>" CompDocCtor ::= "document" EnclosedExpr CompElemCtor ::= "element" (QName | EnclosedExpr) "{" Expr? "}" CompAttrCtor ::= "attribute" (QName | EnclosedExpr) "{" Expr? "}" CompTextCtor ::= "text" "{" Expr? "}" CompNsCtor ::= "namespace" NCName "{" Expr "}" CompCommentCtor::= "comment" "{" Expr "}" CompPiCtor ::= "processing-information" ("{" Expr "}")? "{" Expr? "}" ElemContent ::= ElementChar | Content | ElementCtor | CdataSection | XmlComment | XmlPI AttrList ::= (S (QName S? "=" S? AttrValue)?)* AttrValue ::= ('"' (EscapeQuot | AttrContent)* '"') | ("'" (EscapeApos | AttrContent)* "'") AttrContent ::= QuoteAttrChar | AposAttrChar | Content Content ::= CharRef | "{{" | "}}" | EnclosedExpr | EntityRef EnclosedExpr ::= "{" Expr "}" TypeDecl ::= "as" SequenceType SingleType ::= AtomicType "?"? SequenceType ::= ItemType Occurrence? | "empty" "(" ")" ItemType ::= AtomicType | KindTest | "item" "(" ")" Occurrence ::= "?" | "*" | "+" AtomicType ::= QName KindTest ::= DocumentTest | ElementTest | AttributeTest | PITest | CommentTest | TextTest | AnyKindTest ElementTest ::= "element" "(" (SchemaCtxtPath QName | NodeName ("," TypeName "nillable"?)? )? ")" AttributeTest ::= "attribute" "(" (SchemaCtxtPath "@" QName | "@" NodeName ("," TypeName)?)? ")" NodeName ::= QName | "*" TypeName ::= QName | "*" PITest ::= "processing-instruction" "(" String? ")" DocumentTest ::= "document-node" "(" ElementTest? ")" CommentTest ::= "comment" "(" ")" TextTest ::= "text" "(" ")" AnyKindTest ::= "node" "(" ")" SchemaCtxtPath ::= SchemaGlobCtxt "/" (SchemaCtxtStep "/")* SchemaCtxtLoc ::= (SchemaCtxtPath QName) | SchemaGlobType SchemaImport ::= "import" "schema" SchemaPrefix? String ("at" String)? SchemaPrefix ::= ("namespace" NCName "=") | ("default" "element" "namespace" "=") SchemaMode ::= "lax" | "strict" | "skip" SchemaGlobType ::= "type" "(" QName ")" SchemaGlobCtxt ::= QName | SchemaGlobType SchemaCtxtStep ::= QName QName ::= (NCName ':')? NCName Variable ::= "$" QName Integer ::= Digits Decimal ::= ("." Digits) | (Digits "." [0-9]*) Double ::= (("." Digits) | (Digits ("." [0-9]*)?)) ("e" | "E") ("+" | "-")? Digits String ::= ('"' (EntityRef | CharRef | EscQuot | [^"&])* '"') | ("'" (EntityRef | CharRef | EscApos | [^'&])* "'") EscQuot ::= '"' '"' EscApos ::= "''" S ::= (#x20 | #x9 | #xD | #xA)+ Comment ::= "(:" (Char | Comment)* ":)" Pragma ::= "(::" "pragma" QName Char* "::)" Extension ::= "(::" "extension" QName Char* "::)" EntityRef ::= "&" ("lt" | "gt" | "amp" | "quot" | "apos") ";" Digits ::= [0-9]+ HexDigits ::= ([0-9] | [a-f] | [A-F])+ CharRef ::= "&#" (Digits | ("x" HexDigits)) ";" ElementChar ::= Char - [{}<&] QuoteAttrChar ::= Char - ["{}<&] AposAttrChar ::= Char - ['{}<&] Char ::= [http://www.w3.org/TR/REC-xml#NT-Char] NCName ::= [http://www.w3.org/TR/REC-xml-names/#NT-NCName]
Copyright © 1998–2004 World Wide Web Consortium, (Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved.
XQuery prohibits the following keywords from being used as un-prefixed user-defined function names (however, you may still use them as the prefix or local parts of a qualified name): if
, typeswitch
, node
, comment
, text
, and processing-instruction
.
Except for this special case, XQuery doesn't reserve any keywords. For example, it is perfectly legal to write an XQuery like the one in Listing E.2.
Example E.2. XQuery doesn't reserve keywords
declare namespace namespace="namespace"; declare namespace as="as"; declare function function($function as as:as) returns item* { for $for in in return return };
In this silly example, keywords like namespace
and as
are used as namespace prefixes, the function
keyword is used as function and variable names, the for
keyword is used as a variable name, and the in
and return
keywords are used as element names for path navigation.
Of course, you shouldn't write queries like this unless you're trying to win an Obfuscated XQuery contest (and then you should be prepared to beat queries like the ones in Listing E.3).
As a consequence of the grammar, the XQuery operators satisfy the precedence listed in Table E.1. Operators are listed from highest to lowest precedence, with operators of the same precedence sharing the same row in the table.
Table E.1. XQuery operator precedence (highest to lowest)
Operators | Associativity |
---|---|
| left to right |
| left to right |
| right to left |
| left to right |
intersect except | left to right |
union | | left to right |
+ - (unary) | right to left |
* div idiv mod | left to right |
+ - (binary) | left to right |
| left to right |
= != < <= << >> >= > eq ne lt le gt ge is | left to right |
| left to right |
| left to right |
| left to right |
| left to right |
| left to right |
FLWOR some every typeswitch if or | left to right |
| left to right |
18.191.213.215