3 表达式
基本表达式包括变量引用 ( VariableReference )、 文字串、数字和函数调用,可以使用圆括号。
Expr | ::= | |||
PrimaryExpr | ::= | |||
| '(' Expr ')' | ||||
| Literal | ||||
| Number | ||||
函数调用表达式使用函数名标识上下文函数库中的函数,计算参数并转化成函数要求的数据类型,然后调用函数并返回函数的结果。参数类型转换遵循对应函数(string 、boolean 、number 、node-set )的转换规则。
FunctionCall | ::= | FunctionName '(' ( Argument ( ',' Argument )* )? ')' | ||
Argument | ::= |
地址路径可作为表达式使用,表达式的值即路径选择的节点集。运算符| 用于集合的并操作,操作数必须是节点集。使用谓词筛选的表达式,其值也必须是节点集。谓词的含义和轴关系密切。比如preceding::foo[1] 返回反文档顺序的第一个foo 元素,因为作用于谓词[1] 的是preceding 轴;而 (preceding::foo)[1] 返回按文档顺序的第一个foo 元素,因为作用于谓词[1] 的轴是axis 。
/ 和// 运算符可作为表达式和相对地址路径。如果是表达式,结果必须是节点集。在表达式中/ 的用法和在地址路径中相同。和地址路径中一样,// 代表/descendant-or-self::node()/ 。
其他任何类型都不能转化成节点集。
UnionExpr | ::= | |||
PathExpr | ::= | |||
| FilterExpr '//' RelativeLocationPath | ||||
FilterExpr | ::= | |||
Or 表达式分别计算两个操作数并转化Boolean 值,如果左侧表达式的结果为真则不再计算右侧表达式。And 表达式,如果左侧表达式不成立,则返回false 而不再计算右侧表达式。
EqualityExpr (不仅仅是 RelationalExpr )或者 RelationalExpr (不仅仅是 AdditiveExpr )要比较两个操作数计算得到的对象。对象比较的定义分三个阶段:根据非节点集的比较定义节点集的比较,对于= 、!= 、<= 、< 、>= 、> 都是一样的;定义不涉及节点集的= 和!= 比较;定义不涉及节点集的<= 、< 、>= 和> 比较。
如果比较的两个对象都是节点集,当且仅当第一个节点集中有一个节点A ,第二个节点集中有一个节点B ,A 和B 的字符串值执行该比较成立,比较的结果为ture 。如果一个对象是节点集,另一个对象是数字,当且仅当节点集中存在某个节点的字符串值使用number 转化为数字和数字操作数比较为真是结果为true 。如果一个对象是节点集,另一个是字符串,当且仅当节点集中存在某个节点的字符串值和字符串操作数比较为真时结果为true 。如果一个对象是节点集,另一个是Boolean ,则将节点集使用boolean 函数转化成布尔值再进行比较。
如果操作数没有节点集,而运算符是= 或!= ,则按照下述规则转换然后进行比较。若操作数至少有一个是boolean ,则转化为boolean 进行比较;否则,若操作数中有数字,则转化为数字进行比较;否则按字符串进行比较。两个对象相等,则= 比较为true ;不等则!= 比较为true 。数字按照IEEE754 进行相等比较,同为true 或同为false 的两个布尔值相等。字符串按UCS 字符序列比较。
注意:若$x 绑定到一个节点集, $x="foo" 的含义不同于not($x!="foo") :当且仅当$x 存在某个节点的字符串值为foo 时成立,后者则要求所有节点的字符串值都是foo 。
若比较的对象没有节点集,运算符为<= 、< 、>= 或> ,则将操作数转化为数字根据IEEE754 进行比较。
OrExpr | ::= | |||
AndExpr | ::= | |||
| AndExpr 'and' EqualityExpr | ||||
EqualityExpr | ::= | |||
| EqualityExpr '=' RelationalExpr | ||||
| EqualityExpr '!=' RelationalExpr | ||||
RelationalExpr | ::= | |||
| RelationalExpr '<' AdditiveExpr | ||||
| RelationalExpr '>' AdditiveExpr | ||||
| RelationalExpr '<=' AdditiveExpr | ||||
| RelationalExpr '>=' AdditiveExpr |
注意,上述文法相当于指定运算符的优先级为(从低到高):①or 、②and 、③= 和!= 、④<=, <, >= 和> ,运算符结合的顺序为从左至右。
数字表示浮点数,可以是任何IEEE754 定义的双精度64 位格式的数字,其中包括NaN 、正无穷和负无穷、正零和负零这些特殊的数字,4.2.3 节介绍了IEEE754 的一些主要规定。数学运算符需要将操作数转化成数字。支持的数学运算包括+ 、- 、* 、div (浮点除法)、mod (求余)。
注意:XML 允许在名称中使用连字符,为了区分,作为数学运算符使用时,- 号前面通常需要增加一个空格。模运算采用Java 和ECMAScript 的% 定义,而不同于IEEE754 ,比如5 mod -2 = 1 ,-5 mod 2 = -1 ,-5 mod -2 = -1 。
数字表达式
AdditiveExpr | ::= | |||
MultiplicativeExpr | ::= | |||
| MultiplicativeExpr 'div' UnaryExpr | ||||
| MultiplicativeExpr 'mod' UnaryExpr | ||||
UnaryExpr | ::= | |||
| '-' UnaryExpr |
XPath 中的字符对应一个Unicode 抽象字符,并有对应的Unicode 标量值。但要记住,Unicode 标量值不同于UTF-16 编码值:Unicode 码位大于U+FFFF 的Unicode 编码使用两个16-bit Unicode 码值表示。很多编程语言中,字符串用UTF-16 代码值表示,必须保证能够正确解释成一个字符。
词法分析按照最长匹配原则返回记号。
为便于阅读表达式中可使用空白字符。
如果存在前导记号,而前导记号不是@ 、:: 、( 、[ 或者运算符,则应将* 解释为乘法运算符,NCName 解释为操作数名。
如果NCName 后的字符(可能中间有空格)是( ,则该记号应解释为节点类型或者函数名。
如果NCName 后面是:: ,则应解释为轴名。
否则,记号就不能解释为乘法运算符、操作数名称、节点类型、函数名或者轴名。
表达式词法结构
ExprToken | ::= | '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::' | ||
| NameTest | ||||
| NodeType | ||||
| Operator | ||||
| AxisName | ||||
| Literal | ||||
| Number | ||||
Literal | ::= | '"' [^"]* '"' | ||
| "'" [^']* "'" | ||||
Number | ::= | |||
| '.' Digits | ||||
Digits | ::= | [0-9]+ | ||
Operator | ::= | |||
| '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>=' | ||||
OperatorName | ::= | 'and' | 'or' | 'mod' | 'div' | ||
MultiplyOperator | ::= | '*' | ||
FunctionName | ::= | |||
VariableReference | ::= | '$' QName | ||
NameTest | ::= | '*' | ||
| NCName ':' '*' | ||||
| QName | ||||
NodeType | ::= | 'comment' | ||
| 'text' | ||||
| 'processing-instruction' | ||||
| 'node' | ||||
ExprWhitespace | ::= |
Function: number last ()
返回一个数字,等于表达式求值上下文的大小。
Function: number position ()
返回一个数字,等于表达式求值上下文的位置。
Function: number count (node-set )
返回参数node-set 中的节点个数。
Function: node-set id (object )
按照ID 选择元素。如果参数是一个节点集,则以每个节点的字符串值作为ID 返回具有这些id 的节点组成的节点集。如果参数是其他类型,则转化成字符串,将字符串分解成空白字符分隔的记号,以这些记号作为ID 检索对应的节点,返回这些节点组成的节点集。
id("foo") 选择ID foo 的元素
id("foo")/child::para[position()=5] 选择ID foo 的第五个para 孩子
Function: string local-name (node-set ?)
返回节点集中按文档序第一个节点的扩展名的本地部分。如果参数node-set 为空或者第一个节点没有扩展名返回空白字符串。如果省略参数,返回上下文节点的本地名。
Function: string namespace-uri (node-set ?)
返回节点集中按文档序第一个节点的扩展名的名称空间URI 。如果节点集为空或者第一个节点没有扩展名、扩展名的名称空间URI 为空,返回空白字符串。如果参数省略,则返回上下文节点的名称空间URI 。该函数仅用于元素节点和属性节点,对于其他类型的节点返回空白字符串。
Function: string name (node-set ?)
返回节点的扩展名。除了元素和属性节点外,结果和local-name 相同。
Function: string string (object ?)
将object 参数转化成字符串:
l 节点集:按照文档顺序第一个节点的字符串值,空节点集返回空白字符串。
l 数字:
n NaN 转化成字符串NaN ,
n 正零/ 负零转化成字符串0
n 正无穷转化成字符串Infinity
n 负无穷转化成字符串-Infinity
n 整数转化成没有小数点和前导零的小数形式,负数前加-
l 逻辑值:“假”转化成字符串false ,“真”转化成true 。
l 其他:依赖于具体的类型。
如果省略参数,返回上下文节点的字符串值。
注意,该函数的目的不是将数字转化成供用户阅读的字符串表示,XSLT 中的format-number 函数和xsl:number 元素提供了这样的功能。
Function: string concat (string , string , string *)
连接字符串。
Function: boolean starts-with (string , string )
第二个参数是否是第一个参数的前缀
Function: boolean contains (string , string )
第二个参数是否是第一个参数的子串。
Function: string substring-before (string , string )
返回串1 中串2 之前的子串,若串2 不是串1 的子串则返回空字符串,如substring-before("1999/04/01","/") 返回1999 。
Function: string substring-after (string , string )
返回串1 中串2 之后的子串,若串2 不是串1 的子串则返回空字符串,如 substring-after("1999/04/01","/") 返回 04/01 ,substring-after("1999/04/01","19") 返回99/04/01 。
Function: string substring (string , number , number ?)
返回子串,第二个参数指定起始位置,第三个参数指定子串长度(省略的话延伸到串的结束位置。第一个字符的位置是1 。返回串包含的第一个字符的位置应大于等于第二个参数的圆整值,最后一个字符小于等于后两个参数的圆整值之和。下面是一些特例:
substring("12345", 1.5, 2.6) "234"
substring("12345", 0, 3) "12"
substring("12345", 0 div 0, 3) ""
substring("12345", 1, 0 div 0) ""
substring("12345", -42, 1 div 0) "12345"
substring("12345", -1 div 0, 1 div 0) ""
Function: number string-length (string ?)
返回参数的长度,省略的话返回上下文节点字符串值的长度。
Function: string normalize-space (string ?)
返回参数规范化空白字符后的字符串,即删除前导和尾部空白字符以及多于的空白字符。若省略参数,则返回上下文节点字符串值的规范化串。
Function: string translate (string , string , string )
把串1 中出现的串2 中的字符用串3 中对应位置的字符替换,并返回替换后的串1 。若串2 中的字符在串3 中没有对应的字符(即比串3 长),则删除串1 中对应的字符。若串2 中的字符有重复则以第一个为准;若串3 长于串2 则忽略多于的字符。如translate("bar","abc","ABC") 返回Bar , translate("--aaa--","abc-","ABC") 返回"AAA" 。该函数可用于大小写替换,但是并非是用于所有语言。
Function: boolean boolean (object )
将参数转化成布尔值:
数字:处正/ 负零、NaN 之外都返回true
节点集:非空集返回true
字符串:非空字符串返回true
其他:取决于具体的类型
Function: boolean not (boolean ) 取反
Function: boolean true ()
Function: boolean false ()
Function: boolean lang (string )
判断上下文节点用xml:lang 属性指定的语言是否参数指定的语言或者它的一种子语言。上下文节点的语言由上下文节点或者其最近祖先节点的lang 属性指定。若没有指定,该函数返回false 。如果指定了lang 属性,且与参数相同或者“- ”之前的部分与参数相同,则返回true 。比如lang("en") 对于下列元素返回true :
<para xml:lang="en"/>
<div xml:lang="en"><para/></div>
<para xml:lang="EN"/>
<para xml:lang="en-us"/>
Function: number number (object ?)
只包含数字、负号(- )和前导空白的字符串转化成最接近的IEEE754 数字,否则转化成NaN 。布尔值true 转化成1 ,false 转化成0 。节点集首先转化成字符串然后再转化成数字。省略参数的话将上下文节点的字符串值转化成数字。注意,不要把number 函数用于转化XML 中的元素,除非确知它表示的是数字。
Function: number sum (node-set )
对参数node-set 中节点的字符串值求和。
Function: number floor (number )
Function: number ceiling (number )
Function: number round (number )
返回最接近参数的整数。如果有两个这样的整数,返回较大的一个;NaN 返回NaN ,正无穷返回正无穷,负无穷返回负无穷,正零返回正零,负零返回负零,[-0.5,0) 返回负零。注意,后两条规则不符合floor(x+0.5) 。
XPath 将XML 文档作为树来操作。下面说明XPath 如何建立XML 文档树模型。这个模型仅仅是概念上的,并不要求实现一定采用这样的模型。该模型与XML 信息集的关系参见附录B 。
XML 树可以包含七种类型的节点:根、元素、文本、属性、处理指令、注释、名称空间。每种类型都有确定节点字符串值的方式。有些类型的字符串值是节点的一部分,另一些则计算后代节点的字符串值来得到。
注意: 对于元素节点和根节点,字符串值不同于DOM nodeValue 方法返回的字符串。
有些节点类型还有扩展名,扩展名分为本地部分和名称空间URI 。本地部分是一个字符串,名称空间URI 可以是空或者字符串。名称空间可以是RFC2396 定义的URI 引用,就是说可以包含片段标识符,也可以是相对URI 。在名称空间处理过程中相对URI 可以解析成绝对 URI ,XPath 数据模型中的名称空间URI 必须是绝对URI 。扩展名相等意味着本地部分相同,并且扩展名的名称空间URI 相同(允许都为空)。
文档序指的是文档中所有节点XML 表示的第一个字符在文档(展开一般实体表示之后)中出现的顺序。根节点永远是第一个节点,元素节点出现在孩子节点之前,就是说元素节点的顺序依赖于起始标签的位置。名称空间节点定义在属性节点之前,属性节点定义在孩子节点之前。名称空间的相对顺序、属性的相对顺序由实现决定。逆文档序与文档序相反。
根节点和元素节点的孩子组成一个有序列表。节点的孩子不允许交叉。除了根节点之外,每个节点有且只有一个父节点,父节点只能是根节点或元素节点。根节点或元素节点是所有孩子节点的父节点。后代包括节点的所有孩子及所有孩子的后代。
根节点是树的根,而且只能作为根出现。文档元素节点是根节点的一个孩子,除此之外,出现在文档元素之前(序言部分)和之后的处理指令与注释也是根节点的孩子节点。
根节点的字符串值是其所有文本节点后代的字符串值按照文档顺序串接起来的字符串。
根节点没有扩展名。
文档中每个元素都对应一个元素节点。元素节点有扩展名,如果QName 没有前缀并且没有可用的默认名称空间,扩展名的名称空间URI 为空。
注意,根据XML Names 附录A.3 中的说明,扩展名的本地部分对应ExpEType 的type 属性,名称空间URI 对应ExpEType 元素的ns 属性,若ExpEType 的ns 属性省略,则名称空间URI 为空。
元素节点的孩子包括作为元素内容的元素、注释、处理指令和文本节点。实体引用展开,字符引用解析。
元素节点的字符串值定义为所有文本节点后代字符串值按照文档序串接而成的字符串。
元素节点可以拥有唯一标识符ID ,ID 必须在DTD 中声明,没有DTD 则文档中不能出现ID 。不允许两个元素具有相同的ID 。
元素节点允许有一组关联的属性节点,元素是这些属性节点的父节点,但属性节点不是父元素的孩子。
注意:与此不同的是,DOM 不认为元素是属性的父节点。
属性节点不能同时属于两个元素。
注意:= 运算法检查两个节点的值是否相等,而不是说是否是同一个节点。两个不同元素的属性可以使用= 进行比较,也是值比较。
若DTD 中声明了#IMPLIED 属性,而在元素中没有指定该属性,则元素属性集中没有与该属性对应的节点。
属性如xml:lang 和xml:space 等,其作用范围延伸到元素的所有后代,直到被后代元素相同属性覆盖为止。但是只有定义该属性的元素中包括相应属性节点。
属性节点的扩展名与元素类型。
属性节点的字符串值即XML 标准中定义的规范化值,允许是零长度字符串。
声明名称空间的属性没有对应的属性节点。
每个元素都有一组关联的名称空间节点,分别对应作用域内的各个名称空间前缀(包括xml 前缀)和默认名称空间。元素是这些名称空间节点父节点,但这些名称空间节点不是该元素节点的孩子。每个名称空间节点只能属于一个元素节点。元素包含的名称空间节点包括:
l 该元素本身以xmlns: 开始的每个属性;
l 该元素所有祖先以xmlns: 开始的属性,后面定义的相同前缀覆盖前面的;
l 该元素或其祖先中非空的xmlns 属性(默认名称空间),xmlns="" 相当于取消了默认名称空间声明。
名称空间节点的扩展名中,本地部分即前缀,名称空间URI 恒为空。
名称空间节点的字符串值即绑定到前缀的URI 。
每个处理指令都有对应的处理指令节点,但文档类型声明中的处理指令除外。处理指令扩展名的本地部分即target ,名称空间URI 恒为空。名称空间节点的字符串值为target 之后?> 之前的部分,去掉前导空格。
注意:XML 声明不是处理指令,也没有对应的处理指令节点。
每个注释都有对应的注释节点,但不包括文档类型声明中的注释。注释的字符串值即注释的内容,不含<! — 和--> 。注释没有扩展名。
字符数据包装在文本节点中,所有相邻的字符数据都纳入一个文本节点,因此文本节点没有兄弟节点。文本节点的字符串值即其中的所有字符数据。文本节点至少要包含一个数据字符。
CDATA 节中的所有字符都被视为字符数据。源文档中的<![CDATA[<]]> 将被作为< 处理。因此,CDATA 节的处理就像但与去掉<![CDATA[ 和]]> ,然后将所有的< 和& 替换为< 和 & 。
注释、处理指令和属性值中的字符不生成文本节点。外部实体中的换行规范化为#xA 。
文本节点没有扩展名。