天天看點

【譯文】《XQuery 1.0: An XML Query Language 2004-7-23 草案 第四章》

4 子產品與序言 Modules and Prologs
[1]    Module    ::=    VersionDecl? (MainModule | LibraryModule)
[3]    MainModule    ::=    Prolog QueryBody
[4]    LibraryModule    ::=    ModuleDecl Prolog
[6]    Prolog    ::=    (Setter Separator)* ((Import | NamespaceDecl | VarDecl | FunctionDecl) Separator)*
[7]    Setter    ::=    XMLSpaceDecl | DefaultCollationDecl | BaseURIDecl | ConstructionDecl | DefaultNamespaceDecl | DefaultOrderingDecl
[8]    Import    ::=    SchemaImport | ModuleImport
[9]    Separator    ::=    ";"
[25]    QueryBody    ::=    Expr

[定義:一個查詢可以由一個或多個稱為

子產品

modules

)的片斷裝配而成。每個子產品是一個主子產品(main module)或者庫子產品(library module)。]每個子產品依次由一個或多個稱為子產品資源(module resources)的部分組成。[定義:每個

子產品資源

module resource

)是一段XQuery代碼,符合子產品(Module)文法并且能獨立地經過

2.2.3 Expression Processing

中說明的靜态分析階段(static analysis phase)。]

[定義:一個

主子產品

main module

)由包含一個序言(Prolog)及其後的一個查詢體(Query Body)的單個子產品資源構成。] 一個查詢有一個确定的主子產品。在一個主子產品中,查詢體(Query Body)能被計算,其值是查詢的結果。

[定義:不包含查詢體(Query Body)的子產品稱為庫子產品(

library module

)。] 一個庫子產品可能由多個子產品資源(module resources)組成,每個子產品資源包含一個子產品聲明(module declaration)及其後的序言(Prolog)。多個子產品資源如果在其子產品聲明中命名同樣的目标名字空間(target namespace),則被被視為同一庫子產品的部分。一個庫子產品不能直接被計算;相反的,它提供可以被導入到其他子產品的函數和變量聲明。

沒有子產品資源(module resource)能既包含子產品聲明(module declaration)又包含查詢體(Query Body)。

[定義:

序言

Prolog

)是一連串的聲明和導入,為包含序言的子產品資源(module resource)定義處理環境] 每個聲明或者導入跟着一個分号。[定義:序言中的某些聲明稱為

給定器

setters

),因為他們設定某些影響查詢處理的性質的值,例如構造模式、排序模式、或者預設校對。] 這些給定器如果存在,必須出現在序言的開始,以任何次序。一個序言也可以包含模式和子產品導入,和名字空間字首、變量和函數的聲明。 [定義:每個導入模式或子產品由其

目标命名空間

target namespace

)識别, 就是由模式或子產品定義的對象(如元素或函數)的命名空間。]

[定義:

查詢體

Query Body

)如果存在,由一個規定查詢結果的表達式組成。] 表達式的計算在中

3 Expressions

說明。一個子產品隻有當它有查詢體時才被計算。

4.1 版本聲明 Version Declaration
[2]    VersionDecl    ::=    "xquery" "version" StringLiteral Separator

[定義:任意子產品資源(module resource)可以包含一個

版本聲明

version declaration

)。如果存在,版本聲明出現在子產品資源(module resource)的開始,且為子產品資源(module resource)識别可用的XQuery文法和語義。] 版本号“1.0”表明子產品資源(module resource)必須由一個XQuery版本1.0處理器來處理的需求。如果版本聲明不存在,則版本被假設為“1.0”。當一個XQuery實作處理一個用其不支援的版本标志的子產品資源(module resource)時,必須傳回一個靜态錯誤(static error)。[err:XQ0031] XQuery工作組這樣做的意圖是給出這個規範數字不同于“1.0”的随後的版本,但是這個意圖不表明承諾提出任何XQuery的未來版本,如果提出來也不一定使用任一特定的數字模式。

下面是一個版本聲明的例子:

xquery version "1.0";

4.2 子產品聲明 Module Declaration
[5]    ModuleDecl    ::=    "module" "namespace" NCName "=" StringLiteral Separator

[定義:

子產品聲明

module declaration

)用于辨別一個子產品資源(module resource)為一個庫子產品(library module)的一部分。一個子產品聲明由關鍵字module及其後一個命名空間字首和一個包含合法的URI的串文字組成。[err:XQ0046]] URI辨別庫子產品的目标命名空間(target namespace),這是由這個庫檔案導入的所有變量和函數的命名空間。庫子產品中聲明的每一個變量和函數的名字必須有一個與子產品的目标命名空間同樣的命名空間URI。[err:XQ0048]

任意一個子產品資源(module resource)都可以以子產品導入(module import)的方式導入一個庫子產品,子產品導入(module import)指定要導入的庫子產品的目标命名空間。當一個子產品導入一或多個庫子產品時,被導入子產品的變量和函數聲明将加到此子產品的靜态語境(static context)和(如果可用)動态語境(dynamic context)中。

下面是一個子產品聲明的例子:

module namespace math = "http://example.org/math-functions";

4.3 Xmlspace 聲明 Xmlspace Declaration
[11]    XMLSpaceDecl    ::=    "declare" "xmlspace" ("preserve" | "strip")

[定義:序言(Prolog)中的

xmlspace 聲明

xmlspace declaration

)控制邊界空格(boundary whitespace)是否被直接元素構造器(direct element constructors)在查詢執行時保留。] 如果指定xmlspace preserve,則邊界空格被保留。如果指定xmlspace strip或者不存在xmlspace聲明,邊界空格被去除(删除)。構造元素中空格的進一步說明可以在

3.7.1.4 Whitespace in Element Content

中找到。

下面是一個xmlspace聲明的例子:

declare xmlspace preserve;

4.4 預設校對聲明 Default Collation Declaration
[14]    DefaultCollationDecl    ::=    "declare" "default" "collation" StringLiteral

序言(Prolog)會聲明一個預設校對(default collation),這是如果沒有其他指定校對時,要求校對的函數和操作符使用的校對的名字。例如,作用于字元串的操作符gt由調用函數fn:compare來定義,其帶有可選的校對參數。既然操作符gt沒有指定一個校對,函數fn:compare使用在序言中指定的預設校對執行。預設校對通過一個必須包含一個合法URI的文字串識别。[err:XQ0046]

如果一個序言沒有指定預設校對,則使用Unicode codepoint collation (http://www.w3.org/2004/07/xpath-functions/collation/codepoint)除非實作提供一個不同的預設校對。

下面是一個預設校對聲明的例子:

declare default collation

         "http://example.org/languages/Icelandic";

如果一個序言指定一個以上的預設聲明,或者指定值不能被一個實作識别為已知校對,将引發一個靜态錯誤(static error)。[err:XQ0038]

4.5 URI 聲明 Base URI Declaration
[15]    BaseURIDecl    ::=    "declare" "base-uri" StringLiteral
URI 聲明

base URI declaration

)指定靜态語境的

URI

base URI

)性質,在解析子產品資源(module resource)内的相對URI時被使用。如果一個序言(Prolog)中發現一個以上的基URI聲明,将引發一個靜态錯誤(static error)[err:XQ0032]。 如果一個基URI聲明中的串文字不包含一個合法URI,将引發一個靜态錯誤(static error)[err:XQ0046]。注意,函數fn:doc使用調用子產品的基URI解析相對URI。

下面是一個基URI聲明的例子:

declare base-uri "http://example.org";

4.6 構造聲明 Construction Declaration
[20]    ConstructionDecl    ::=    "declare" "construction" ("preserve" | "strip")

序言(Prolog)中的

構造聲明

construction declaration

)設定靜态語境(static context)中的構造模式(construction mode)為preserve或strip。構造模式支配元素構造器的行為。如果構造模式為preserve,則一個構造元素節點為xs:anyType,而且這個構造元素節點的屬性和子孫節點保持其原來的類型。如果構造模式為strip,構造元素節點及其所有子節點的類型為xdt:untyped, 構造元素的屬性類型為xdt:untypedAtomic. 元素構造器在

3.7.1 Direct Element Constructors

3.7.3.1 Computed Element Constructors

中說明。

下例說明一個構造聲明:

declare construction strip;

如果一個序言指定多于一個構造聲明,将會引發一個靜态錯誤(static error) [err:XQ0067]

4.7 預設命名空間聲明 Default Namespace Declaration
[12]    DefaultNamespaceDecl    ::=    (("declare" "default" "element") | ("declare" "default" "function")) "namespace" StringLiteral
預設命名空間聲明( Default namespace declarations

用在序言(Prolog)中,來使沒有字首的QName便于使用。在預設命名空間聲明中使用的串文字必須是一個合法的URI或者一個零長串。[err:XQ0046] 下列種類的預設命名空間聲明是支援的:

  • 預設元素 / 類型命名空間聲明 default element/type namespace declaration )聲明一個與無字首的元素和類型名關聯的命名空間URI。此聲明在靜态語境(static context)中記錄為預設元素/類型命名空間(default element/type namespace)。一個序言(Prolog)最多隻可以包含一個預設元素/類型命名空間聲明。[err:XQ0066] 如果預設元素/類型命名空間聲明中的串文字(StringLiteral)是一個零長串,預設元素/類型命名空間(default element/type namespace)被設為“none,”且元素和類型的無字首名字被認為不在命名空間中。下面的例子說明一個預設元素/類型命名空間的聲明:

·        declare default element namespace "http://example.org/names";

預設元素/類型命名空間聲明可能被直接元素構造器(direct element constructor)中的命名空間聲明屬性(namespace declaration attribute)或者計算元素構造器(computed element constructor)中的本地命名空間聲明(local namespace declaration)重載。

  • 預設函數命名空間聲明 default function namespace declaration )聲明一個與函數調用中的無字首函數名相關聯的命名空間URI。 此聲明在靜态語境(static context)中記錄為預設函數命名空間(default function namespace)。一個序言(Prolog)最多隻可以包含一個預設函數命名空間聲明 [err:XQ0066] 。 如果一個預設函數命名空間聲明中串文字(StringLiteral)為一零長串,将引發一個靜态錯誤 [err:XQ0063] 。 如果沒有聲明預設函數命名空間,則預設函數命名空間為XPath/XQuery函數的命名空間,http://www.w3.org/2004/07/xpath-functions (然而,這個預設值可能被一個實作重載。)下面的例子說明預設函數命名空間的聲明:

·        declare default function namespace

·             "http://example.org/math-functions";

聲明一個預設函數命名空間的效果是,預設函數命名空間中包括隐含聲明的構造函數在内的所有函數,都以具有原來的本地名但是沒有命名空間URI的名字為别名。于是函數可以用其原來的名字或者它的别名調用——就是說,命名空間字首成為可選項。當一個函數調用使用一個沒有字首的函數名時,這個函數的本地名必須和一個在預設函數命名空間中的函數(包括隐含聲明的構造函數)相比對。[err:XP0017]

無字首屬性名和變量名不屬于命名空間。

4.8 預設排序聲明 Default Ordering Declaration
[13]    DefaultOrderingDecl    ::=    "declare" "ordering" ("ordered" | "unordered")

[定義:

預設排序聲明

default ordering declaration

)設定靜态語境(static context)中的排序模式(ordering mode)。] 這個排序模式應用于一個子產品資源(module resource)(包括序言(Prolog)和查詢體(Query Body),如果有的話)中的所有表達式,除非被一個ordered 或 unordered表達式重載。如果一個序言(Prolog)中發現多于一個的預設排序聲明,将引發一個靜态錯誤(static error)[err:XQ0065].

排序模式(Ordering mode)影響沒有order by子句的路徑表達式、union、intersect和、except表達式和FLWOR表達式的行為。如果排序模式為ordered,由路徑、union、intersect和、except表達式傳回的節點序列為文檔順序(document order);否則,這些傳回序列的次序為依賴實作的(implementation-dependent)。排序模式對FLWOR表達式的影響在

3.8 FLWOR Expressions

中說明。

下例說明一個預設排序聲明:

declare ordering unordered;

4.9 模式導入 Schema Import
[16]    SchemaImport    ::=    "import" "schema" SchemaPrefix? StringLiteral (("at" StringLiteral) ("," StringLiteral)*)?
[17]    SchemaPrefix    ::=    ("namespace" NCName "=") | ("default" "element" "namespace")

[定義:

模式導入

schema import

)把元素、屬性和類型定義從模式導入到模式定義作用域(in-scope schema definitions)中。] 将被導入的模式由其目标命名空間(target namespace)辨別。模式導入會給已導入模式綁定一個命名空間字首,或者會聲明目标命名空間為預設元素/類型命名空間(default element/type namespace)模式導入也會為模式的定位提供可選提示。

一個模式導入中的串文字必須是合法的URI。 [err:XQ0046]  這些串文字的開始指定了将要導入的模式的目标命名空間。接在關鍵字後面的串文字是可選的位置提示,可以以依賴實作的方式被解釋或者不予處理。多個位置提示被用來訓示多于一個的可能位置,來尋找模式或者多個組成模式的實際資源。

指定一個零長串為目标命名空間的模式導入,被認為是導入一個沒有命名空間的模式。這樣的模式導入可以不必綁定一個命名空間字首 [err:XQ0057],但是它會設定預設元素/類型命名空間為“no namespace”,允許導入的名字空間中的定義被引用。如果預設元素/類型命名空間沒有設定為“no namespace”,就沒有辦法引用沒有目标命名空間的導入模式中的定義。

如果同一個序言(Prolog)中多于一個的模式導入指定同一個目标命名空間,将引發靜态(static error)錯誤。[err:XQ0058] 如果實作不能通過查找一個具有指定目标命名空間的合法的模式處理一個模式導入,将引發靜态錯誤(static error)[err:XQ0059]。如果多個導入的模式或者多個同一模式内的實際資源,包含對相同符号空間(例如,對同樣的元素名的兩個定義,甚至是一緻的定義)中相同名字的定義,将引發一個靜态錯誤(static error)[err:XQ0035]。然而,以目标命名空間http://www.w3.org/2001/XMLSchema(預定義字首xs)導入的模式,不産生錯誤,即使這個模式中定義的内部類型隐含的包括在類型定義作用域(in-scope type definitions)中。

下面的例子為一個XHTML文檔導入模式,指定其目标命名空間及其位置,并綁定字首xhtml到此命名空間:

import schema namespace xhtml="http://www.w3.org/1999/xhtml"

   at "http://example.org/xhtml/xhtml.xsd";

下面的例子通過僅僅指定其目标命名空間導入一個模式,并使其成為預設元素/類型命名空間:

import schema default element namespace "http://example.org/abc";

下面的例子導入一個沒有目标命名空間的模式,提供一個位置提示,并設定預設元素/類型命名空間為“no namespace”以便導入模式中的定義可以被引用:

import schema default element namespace ""

at "http://example.org/xyz.xsd";

下面的例子導入一個沒有目标命名空間的模式,并設定預設元素/類型命名空間為“no namespace”。由于沒有提供位置提示,它可用于實作來查找被導入的模式。

import schema default element namespace "";

4.10 子產品導入 Module Import
[18]    ModuleImport    ::=    "import" "module" ("namespace" NCName "=")? StringLiteral (("at" StringLiteral) ("," StringLiteral)*)?

[定義:

子產品導入

module import

)從一個庫子產品(library module)導入函數聲明和變量聲明到被導入子產品資源(module resource)的函數簽名(function signatures)和變量作用域(in-scope variables)中。] 要被導入的子產品由其目标命名空間(target namespace)确定。子產品導入會把一個命名空間字首與被導入子產品的目标命名空間綁定,而且它會為定位被導入子產品的子產品資源(module resources)提供可選的提示。

一個子產品導入中的串文字必須是合法的URI。[err:XQ0046] 這些串文字的開始指定了被導入子產品的目标命名空間。在關鍵字後面的串文字為可選的定位提示,能夠以一種實作定義(implementation-defined)的方式被解釋或者不予處理。如果被導入子產品由多個子產品資源(module resources)組成,這些子產品資源中的所有函數和變量聲明都将被導入。

如果在一個序言(Prolog)中有多于一個的子產品導入指定同一個目标命名空間,将引發一個靜态錯誤(static error)[err:XQ0047]。如果被導入子產品和導入子產品的目标命名空間相同,将引發一個靜态錯誤[err:XQ0056] 。如果實作不能通過查找一個由指定目标命名空間定義的合法子產品,來處理一個子產品導入,将引發靜态錯誤(static error)[err:XQ0059]。如果多個被導入子產品或者一個被導入子產品内的多個子產品資源(module resources),包含對同一符号空間(例如,同一函數的兩個定義,甚至是一緻的定義)的同一名字的定義,将引發一個靜态錯誤(static error)[err:XQ0034][err:XQ0049]。

每個子產品資源(module resource)有其自身的靜态語境(static context)。一個子產品導入(module import)僅導入函數和變量聲明;不從被導入子產品中導入其他對象,比如其模式定義作用域(in-scope schema definitions)或者靜态已知命名空間(statically known namespaces)。子產品導入不可傳遞——就是說,導入一個子產品隻提供對直接包含在被導入子產品中的函數及變量聲明的通路。例如,如果子產品A導入子產品B,并且子產品B導入子產品C,子產品A沒有通路C中聲明的函數和變量的權力。兩個子產品可以互相導入。

如果導入子產品的類型定義作用域(in-scope type definitions)不包括被導入子產品中出現的變量聲明、函數參數或函數傳回值的類型名的定義,這樣的子產品導入會引發一個類型錯誤(type error)[err:XQ0036]。導入一個包含其名字已經在導入子產品的靜态語境中聲明過的函數聲明或者變量聲明的子產品,是一個靜态錯誤(static error)[err:XQ0037]。

為了說明上述規則,假定某一個模式定義了一個類型名triangle。假定一個庫子產品導入此模式,将其目标命名空間與字首geometry綁定,并用下面的函數簽名(function signature)聲明了一個函數:math:area($t as geoetry:triangle) as xs:double。如果查詢希望使用這個函數,它必須既導入庫子產品,又導入庫檔案基于的模式。僅僅導入庫子產品不提供對在函數area的簽名中使用的geometry:triangle類型定義的通路。

下面的例子說明一個子產品導入:

import module namespace math = "http://example.org/math-functions";

4.11 命名空間聲明 Namespace Declaration
[10]    NamespaceDecl    ::=    "declare" "namespace" NCName "=" StringLiteral

[定義:

命名空間聲明

namespace declaration

)說明一個命名空間字首并将其與一個命名空間URI關聯,添加(字首,URI)對到靜态已知命名空間(statically known namespaces)集合中。] 在命名空間聲明中使用的串文本必須是一個合法的URI [err:XQ0046] 或者一個零長串。命名空間聲明的作用域貫穿其聲明的整個查詢,除非它被一個直接元素構造器(direct element constructor)中的命名空間聲明屬性(namespace declaration attribute)或者一個計算元素構造器(computed element constructor)中的本地命名空間聲明(local namespace declaration)所重載。

下面的查詢說明一個命名空間聲明:

declare namespace foo = "http://example.org";

<foo:bar> Lentils </foo:bar>

在查詢結果中,新建立的節點是在與命名空間URI http://example.org相關聯的命名空間中的。

一個序言(Prolog)中的同一個命名空間字首的多個聲明,導緻一個靜态錯誤(static error)[err:XQ0033]。然而,一個序言中的一個命名空間的聲明,能重載一個已經在靜态語境中聲明過的字首。

使用一個有一個已經被聲明過的命名空間字首的QName,将引發一個靜态錯誤(static error)。[err:XP0008]

XQuery有幾個預聲明的命名空間字首,它們于每個查詢被處理前,在靜态已知命名空間(statically known namespaces)中給出。這些字首可以在沒有顯式聲明的情況下使用。它們會被序言(Prolog)中的命名空間聲明(namespace declarations)所重載,或者被關于構造元素的命名空間屬性(namespace declaration attributes)或本地命名空間聲明(local namespace declarations)所重載(除了字首xml,它可以不必重新聲明)。預聲明的命名空間字首如下:

  • xml = http://www.w3.org/XML/1998/namespace
  • xs = http://www.w3.org/2001/XMLSchema
  • xsi = http://www.w3.org/2001/XMLSchema-instance
  • fn = http://www.w3.org/2004/07/xpath-functions
  • xdt = http://www.w3.org/2004/07/xpath-datatypes
  • local = http://www.w3.org/2004/07/xquery-local-functions (參見 4.13 Function Declaration .)

附加的預定義命名空間字首可以由實作加到靜态已知命名空間(statically known namespaces)。

命名空間字首也有一個特殊的意義(它辨別一個命名空間聲明屬性(namespace declaration attribute)),并且它不可以被重新聲明。

如果一個命名空間聲明的串文字部分為一零長串,則應用下列規則:

  • 如果實作支援 [XML Names 1.1] ,任何現有的為給定字首綁定的命名空間從靜态已知命名空間(statically known namespaces)中删除。這個特性提供了一個方式,來删除象local這樣的預聲明命名空間字首。
  • 如果實作不支援 [XML Names 1.1],引發一個靜态錯誤。[err:XQ0053]
  • 一個特定的實作是否支援[XML Names 1.1],是由實作定義的。

當元素或者屬性名相比較時,如果它們的本地部分和命名空間URI在碼點基礎上比對,則認為相同。兩個名字的比對不必命名空間字首相同,如下例所示:

declare namespace xx = "http://example.org";

let $i := <foo:bar xmlns:foo = "http://example.org">

              <foo:bing> Lentils </foo:bing>

          </foo:bar>

return $i/xx:bing

盡管命名空間字首xx和foo不同,但都與命名空間URI“http://example.org”綁定。因為xx:bing和foo:bing有相同的本地名和相同的命名空間URI,他們相比對。上述查詢的輸出如下:

<foo:bing> Lentils </foo:bing>

4.12 變量聲明 Variable Declaration
[19]    VarDecl    ::=    "declare" "variable" "$" VarName TypeDeclaration? ((":=" ExprSingle) | "external")
[136]    VarName    ::=    QName
[109]    TypeDeclaration    ::=    "as" SequenceType

變量聲明(

variable declaration

)添加一個變量的靜态類型到變量作用域(in-scope variables)中,也可以為變量添加一個值到變量值(variable values)。如果變量作用域(in-scope variables)中變量的擴充QName(expanded QName)和另一個變量的相同,将引發一個靜态錯誤(static error)[err:XQ0049]。

如果變量聲明包含一個類型,那個類型和變量類型一樣被添加到靜态語境中。如果變量聲明中包含一個不是顯式類型的表達式,變量的靜态類型将通過表達式的靜态類型來推斷。如果一個變量聲明既包含一個類型又包括一個表達式,表達式的靜态類型必須與已聲明的靜态聲明相容;否則将引發一個類型錯誤[err:XP0004]。

[定義:如果一個變量聲明包含一個表達式,這個表達式稱為

初始化表達式

initializing expression

)。] 一個給定變量的初始化表達式必須在任何一個引用此變量的表達式求值之前被求值。一個初始化表達式的靜态語境(static context)包括所有在序言(Prolog)中任何位置聲明或導入的函數,但是它隻包括那些在序言中聲明或導入的比将要被初始化的變量早的變量和命名空間。如果一個初始化表達式由于一個環(例如,它依賴的函數轉過來依賴于将要被初始化的變量的值)而不能被求值,将引發一個靜态錯誤(static error)[err:XQ0054]。

如果變量聲明包含關鍵字external,則在查詢能被求值之前,外部環境必須為變量提供一個值。如果外部變量聲明也包含一個聲明的類型,則由外部環境聲明提供的值必須與聲明的類型一緻,此處應用

2.4.4 SequenceType Matching

中的比對規則(參見

2.2.5 Consistency Constraints

)。如果一個外部變量聲明不包含一個已聲明類型,類型和比對的值必須由外部環境在求值時提供。這樣的變量的靜态類型被認為是item()*。

在一個庫子產品(library module)中聲明的所有變量名必須(當已擴充時)在這個庫子產品的目标命名空間(target namespace)中。[err:XQ0048] 當一個庫子產品被導入時,被導入子產品的變量聲明被添加到導入子產品的變量作用域(in-scope variables)中。

沒有命名空間的變量名不在命名空間中。沒有命名空間字首的變量聲明隻能出現在主子產品中。

術語

變量聲明

variable declaration

)總是指序言(Prolog)中一個變量的聲明。将一個變量綁定到一個查詢表達式(如FLWOR表達式)中的值,稱為

變量綁定

variable binding

)并不使得變量對導入子產品可見。

這是變量聲明的例子:

  • 下面的聲明同時指定一個變量的類型和值。這個聲明使得類型xs:integer與變量$x在靜态語境(static context)中關聯,使得值7與變量$x在動态語境(dynamic context)中關聯。

·        declare variable $x as xs:integer := 7;

  • 下面的聲明指定一個值,但是不指定類型。變量的靜态類型從其值的靜态類型上推斷。這種情況下,從值7.5上推斷出變量$x的靜态類型為xs:decimal。

·        declare variable $x := 7.5;

  • 下面的聲明指定了類型但是沒有指定值。關鍵字external 說明變量的值将由外部環境提供。在求值時,如果動态語境(dynamic context)中的變量沒有類型為xs:integer的值,将引發一個類型錯誤。

·        declare variable $x as xs:integer external;

  • 下面的聲明既沒有指定類型,也沒有指定值。它僅僅聲明了查詢依賴于名為$x的變量的存在,此變量的類型和值将由外部環境提供。在查詢分析期間,的類型被認為是。在查詢求值期間,動态語境(dynamic context)必須包含$x的類型和值,并且其類型和值必須一緻。

·        declare variable $x external;

4.13 函數聲明 Function Declaration

除了在[XQuery 1.0 and XPath 2.0 Functions and Operators]中說明的内置函數之外,XQuery允許使用者聲明他們自己的函數。函數聲明指定函數的名字、參數的名字和資料類型、以及結果的資料類型。所有的資料類型使用

2.4 Types

中描述的文法指定。函數聲明使被聲明的函數被添加到它出現的子產品資源(module resource)的函數簽名(function signatures)中。

[21]    FunctionDecl    ::=    "declare" "function" QName "(" ParamList? (")" | (")" "as" SequenceType)) (EnclosedExpr | "external")
[22]    ParamList    ::=    Param ("," Param)*
[23]    Param    ::=    "$" VarName TypeDeclaration?
[109]    TypeDeclaration    ::=    "as" SequenceType

函數聲明确定一個函數是使用者定義函數(user-defined)還是外部函數(external)。 [定義:對于一個

使用者定義函數

user-defined function

)來說,函數聲明包括一個稱為

函數體

function body

)的表達式,它定義函數結果如何從函數的參數計算得到。] 一個函數體的靜态語境(static context)包括在序言(Prolog)任何地方被聲明或者導入的所有函數,但是它隻包括在序言中聲明或者導入的比函數定義早的變量和命名空間。

[定義:

外部函數

External functions

)是在查詢環境外部被實作的函數。] 例如,除了在[XQuery 1.0 and XPath 2.0 Functions and Operators]中說明的核心函數庫以外,一個XQuery實作會提供一組外部函數。外部函數通過關鍵字external來識别。一個外部函數的函數聲明的目的,是聲明函數參數和結果的資料類型,以便于包含或者導入這個函數聲明的查詢在類型檢查時使用。

一個XQuery實作可能提供一個功能,借此,外部函數能夠用一個宿主程式設計語言(host programming language)實作,但這不是必需的。如果提供了這樣的功能,參數傳遞到一個外部函數、函數結果傳回到調用查詢所使用的協定是實作定義的(implementation-defined)。

一個XQuery實作可能用附加的類型來擴充[XQuery 1.0 and XPath 2.0 Data Model]的類型系統,設計附加的類型易于同宿主程式設計語言交換資料,它也可以為使用者提供定義這樣類型的機制。例如,可以提供一個類型,它封裝一個由外部函數傳回的,象一個SQL資料連接配接那樣的對象。這些附加類型(如果定義了)被認為是由限制從xdt:anyAtomicType派生的。

每個函數必須在一個命名空間中——就是說,每個被聲明的函數名必須(擴充時)有個一非空的命名空間URI[err:XQ0060]。每一個在庫子產品(library module)中聲明的函數名必須(擴充時)在一個庫子產品的目标命名空間(target namespace)中[err:XQ0048]。如果函數聲明中的函數名(在擴充時)不在下列任意一個命名空間中,将引發一個靜态錯誤(static error)[err:XQ0045]:

  • http://www.w3.org/XML/1998/namespace
  • http://www.w3.org/2001/XMLSchema
  • http://www.w3.org/2001/XMLSchema-instance
  • http://www.w3.org/2004/07/xpath-functions
  • http://www.w3.org/2004/07/xpath-datatypes

如果聲明的函數的擴充QName(expanded QName)和參數數目,與函數簽名中的另一個函數的擴充QName(expanded QName)和參數數目相同,将引發一個靜态錯誤 [err:XQ0034]。

為了允許主子產品在不定義一個新的命名空間的情況下,為子產品内本地使用聲明函數,XQuery預定義了到命名空間http://www.w3.org/2004/07/xquery-local-functions的命名空間字首local,并為定義本地函數使用保留這個命名空間。

如果聲明一個函數參數使用一個名字但是沒有類型,它的預設類型為item*。 如果一個函數聲明中省略了結果類型,它的預設結果類型為item*。

一個函數聲明的參數被認為是其作用域為函數體的變量。一個函數聲明如果有一個以上的同名參數,将引發一個靜态錯誤(static error)[err:XQ0039]。函數參數的類型可以是任何用一個序列類型(SequenceType)(參見

2.4 Types

)表示的類型。

下面的例子說明一個本地函數的聲明和使用,它接收一個employee元素的序列,按部門(department)彙總之,傳回一個dept元素序列。

  • 利用一個函數,準備位于丹佛(Denver)的雇員的總計。

·        declare function local:summary($emps as element(employee)*)

·           as element(dept)*

·        {

·           for $d in fn:distinct-values($emps/deptno)

·           let $e := $emps[deptno = $d]

·           return

·              <dept>

·                 <deptno>{$d}</deptno>

·                 <headcount> {fn:count($e)} </headcount>

·                 <payroll> {fn:sum($e/salary)} </payroll>

·              </dept>

·        };

·         

·        local:summary(fn:doc("acme_corp.xml")//employee[location = "Denver"])

将函數參數轉換為它們聲明時的參數類型的規則,和将函數結果轉換成它們聲明的結果類型的規則,在

3.1.5 Function Calls

中說明。

函數聲明可以遞歸——就是說,它可以引用它自己。其函數體互相引用的互相遞歸函數也是允許的。下面的例子聲明了一個遞歸函數,計算一個節點層次的最大深度,并調用此函數來查找一個特定文檔的最大深度。在其聲明中,使用者聲明的函數local:depth調用預設函數命名空間的内置函數empty和max。

  • 查找名為partlist.xml的文檔的最大深度。

·        declare function local:depth($e as node()) as xs:integer

·        {

·           (: A node with no children has depth 1 :)

·           (: Otherwise, add 1 to max depth of children :)

·           if (fn:empty($e/*)) then 1

·           else fn:max(for $c in $e/* return local:depth($c)) + 1

·        };

·         

·        local:depth(fn:doc("partlist.xml"))

因為在類型定義作用域(

constructor function

)中,

構造函數

(in-scope type definitions)已經為每一個使用者定義的原子類型被有效地聲明了,如果序言試圖聲明一個與這些類型中任一個有相同擴充QName(expanded QName)的函數,将引發一個靜态錯誤(static error)[err:XQ0034]

注意:

如果 XQuery 的一個未來版本支援使用者聲明的函數的重載,将會在以一個節點作為參數的函數和同名的以一個原子值為參數的函數之間産生歧義(因為在必要時,一個函數調用自動抽取一個節點的原子值)。一個這樣的 XQuery 未來版本的設計者能通過編寫适當的規則來控制函數重載,進而避免這樣的歧義。盡管如此,涉及到這個可能性的使用者,可以在調用需要原子值的函數時,選擇從節點中顯式地抽取原子值。

上一篇: iOS 截屏監聽