XML 路径语言(XPath)(一)

来源:互联网 发布:ru域名注册 编辑:程序博客网 时间:2024/06/06 00:52
译文XML 路径语言(XPath) (版本  1.0)
( http://www.opendl.com/openxml/w3/TR/xpath/xpath-gb.html )
英文XML Path Language
(http://www.w3.org/TR/xpath)
注意
译者
时间初次定稿:2003 年 2 月 20 日 (NZT)最后修改: 2003 年 8 月 5 日 (UTC)

W3C

XML 路径语言(XPath) 版本 1.0

万维网协会 (W3C) 建议 1999November16

本版本:
http://www.w3.org/TR/1999/REC-xpath-19991116 (其它文件格式: XML [英文] HTML [英文] )
最新版本:
http://www.w3.org/TR/xpath 中文翻译 [简体中文]
以前版本:
http://www.w3.org/TR/1999/PR-xpath-19991008
http://www.w3.org/1999/08/WD-xpath-19990813
http://www.w3.org/1999/07/WD-xpath-19990709
http://www.w3.org/TR/1999/WD-xslt-19990421
编者:
James Clark <jjc@jclark.com>
Steve DeRose, Inso Corp. and Brown University <Steven_DeRose@Brown.edu>

摘要

XPath 是一种用于对 XML 文档的元件寻址的一语言,设计为 XSLT 和 XPointer 使用。

本文档的地位

本文档已由万维网协会 (W3C) 组织成员和其他感兴趣的各方审阅,并已被组织理事批准为万维网协会 (W3C) 建议。这是一个稳定的文档,可以用作参考材料,也可以作为其他文档的标准参考文献。W3C 在建议制定过程中的作用是吸引对本规范的注意并促进它的广泛使用。这能增强 Web 的功能和互操作性。

本规格说明已知的错误列表在 http://www.w3.org/1999/11/REC-xpath-19991116-errata

对本说明的建议可电邮到 www-xpath-comments@w3.org存档的建议可供备查。

英文版是唯一的正式版,本文档的翻译请参见 http://www.w3.org/Style/XSL/translations.html

现有 W3C 建议和其他技术文档的列表在 http://www.w3.org/TR

本规格是 XSL 工作组及 XML 链接工作组联合的工作成果,因此也是 XML 式样制定工作(W3C Style activity)W3C XML 制定工作(W3C XML Activity)的一部分。

目录

1 绪论
2 地址路径
    2.1 地点步进
    2.2
    2.3 节点测试
    2.4 判定词
    2.5 缩简句法
3 表达式
    3.1 基础
    3.2 函数调用
    3.3 节点集合
    3.4 布尔
    3.5 数字
    3.6 字符串
    3.7 词法结构
4 核心函数库
    4.1 节点集合函数
    4.2 字符串函数
    4.3 布尔函数
    4.4 数字函数
5 数据模型
    5.1 根节点
    5.2 元素节点
        5.2.1 唯一 ID
    5.3 属性节点
    5.4 命名空间节点
    5.5 处理指令节点
    5.6 注释节点
    5.7 正文节点
6 一致性

附录

A 参考书目
    A.1 标准规范参考书目
    A.2 其他参考书目
B XML 信息集映射(非标准)


1 绪论

XPath 是努力给 XSL 转换[XSLT]和 XPointer [XPointer]的共享功能提供一个共用的句法及语义的结果。XPath的主要的目是用于对 XML [XML]文档元件寻址。在支持这个主要目的的同时,它也为字符串,数字和布尔的操作提供了基本手段。XPath 使用简明的、非 XML 句法以便於在 URIs 和 XML 属性值以内使用 XPath,XPath 对 XML 文档的抽象的、逻辑的结构而非它的表面句法进行操作,XPath 的名字源于它在 URL 中用作对 XML 文档的层次的结构进行导航一个路径标志。

除了用做寻址外,XPath 也被设计成以便它有能被用于匹配的一个自然的子集(测试一个节点是否匹配一个模式);XSLT中描述了 XPath 在这方面的使用。

XPath 将一个 XML 文档建模成为一棵节点树,有不同类型的节点,包括元素节点,属性节点和正文节点。XPath 定义了一种方法来计算每类的节点的字串值。一些节点的类型也有名字。XPath 充分支持 XML 命名空间[XML Names]。这样,节点的名字被建模成由一个局城部分和可能为空的命名空间 URI 组成的对;这被称为扩展名5 数据模型描述了数据模型详细细节。

XPath的主要语法构件是表达式,一个表达式匹配产生式 Expr,一个表达式被求值评估产出一个对象,该对象有下列 4 种基本的类型之一:

节点集合(无序的、无重复的节点集合)
布尔(真或假)
数字(一个浮点数字)
字符串(UCS 字符的顺序)

表达式求值发生与上下文有关。XSLT 和 XPointer 分别地指定了上下文怎样在 XSLT 和 XPointer 使用 XPath 表达式。上下文组成包括:

一个节点([定义上下文节点])
一对非零正整数([定义上下文位置]和[定义上下文大小])
一个变量绑定的集合
一个函数库
表达式范围内的命名空间声明的集合

上下文位置总是小於或等於上下文的大小。

绑定由从变量名到变量值映射组成,一个变量的值是一个对象,它的类型可以是任何表达式的值可能的类型,并且也可以有这里没指定的另外的类型。

函数库由从函数名到函数的映射组成,每个函数可接受零个或零个以上的参数并且返回单个的结果。本文档定义了所有的 XPath 实现必须支持的一个核心函数库(参看4 核心函数库)。对於核心函数库中的每一个函数,参数和结果有4种基本的类型。XSLT 和 XPointer 通过定义另外的函数来扩展 XPath 的函数;这些函数有些对 4 种基本的类型操作,其它的则对 XSLT 和 XPointer 定义的另外的数据类型操作。

命名空间声明由从前缀到命名空间 URI 的映射组成。

变量绑定、函数库及命名空间声明对於求表达式或其子表达式的值总是一样的;上下文节点、上下文位置及大小对於求表达式或其子表达式的值则是不同的。有多种表达式可改变上下文节点,而只有判定词能改变上下文位置和上下文大小(参看2.4 判定词)。在描述一种表达式的求值时,必须总是明确地说明是上下文节点、上下文位置、还是上下文的大小对子表达式的求值产生变化,如果没有关于上下文节点、上下文位置、上下文的大小的说明,那么对那种表达式的子表达式的求值就保持不变。

XPath 表达式经常出现在 XML 属性里,在本节中说明的语法适用于在 XML 1.0 规范化以后的属性值。因此,如果语法要使用字符 <,而该字符却绝对不能以 < 出现在任何的 XML 资料中,这样必须遵循 XML 1.0 的规则,也就是应键入成 &lt;。在表达式以内,文字的字符串由单引号或双引号来界定,它也用于界定 XML 属性。为了避免 XML 处理器将表达式中的引号解释成属性界定符,引号可以键入成字符参考( &quot;&apos; )。做为选择,如果 XML 属性使用双引号,表达式则可以使用单引号,反之亦然。

一种重要的表达式类型是地点路径,地址路径选择与上下文节点相关的节点集合。对是地址路径的表达式求值的结果是节点集合,该节点集合包含地点路径选择的节点。地址路径能递归地包含表达式,这些表达式用来过滤节点集合。地址路径与此同时LocationPath 相匹配。

在下列语法里,非终结的 QNameNCName 定义在[XML Names]中,而S定义在[XML]中。语法与[XML]一样使用 EBNF 符号表示法(除了总是以大写字母起头的语法符号)。

分析表达式时,首先将字符字符串分解成分割段(token),然后再分析所得分割段结果的序列。空白符能自由地在分割段之间被使用。分段化(tokenization)过程在3.7 词法结构中描述。

2 地址路径

尽管地址路径不是本语言中最完整的语法的构件(地址路径 LocationPathExpr 的一个特殊的例子),他们却是最重要的构件,因此,将首先进行描述。

每一条地址路径都能使用直观但是相当冗长的句法表示,同时也有很多缩简句法可用以简明地表示常见路径。这节将解释使用未经缩写的句法的地址路径的语义。然后将通过显示缩简的句法怎扩展成未经缩写的句法来解释缩简句法(看2.5 缩简句法)。

这是使用未经缩写的句法的地址路径的一些例子:

  • child::para 选择上下文节点的 para 元素孩子

  • child::* 选择上下文节点的所有元素孩子

  • child::text() 选择上下文节点的所有的正文节点

  • child::node() 选择上下文节点的所有的孩子,而不论它们是什么节点类型

  • attribute::name 选择上下文节点的 name 属性

  • attribute::* 选择上下文节点的所有的属性

  • descendant::para 选择上下文节点的 para 元素子孙

  • ancestor::div 选择上下文节点的 div 祖先

  • ancestor-or-self::div 选择上下文节点的 div 祖先,并且,如果上下文节点为 div 元素,则该上下文节点也被选择

  • descendant-or-self::para 选择上下文节点中所有的 div 元素子孙,而且,如果上下文节点是一个 div 元素,则该上下文节点也被选择

  • self::para 如果上下文节点是一个 para 元素,选择该上下文节点,否则不选择任何东西

  • child::chapter/descendant::para 选择上下文节点的 chapter 元素孩子的所有的 para 元素子孙

  • child::*/child::para 选择上下文节点的所有的 para 孙子

  • / 选择文档根(它总是是文档元素的父)

  • /descendant::para 选择在同一文档中所有的 para 元素作为上下文节点

  • /descendant::olist/child::item 选择在同一文档中所有的以 olist 为父的 item 元素作为上下文节点

  • child::para[position()=1] 选择上下文节点的第一个 para 孩子

  • child::para[position()=last()] 选择上下文节点的最后一个 para 孩子

  • child::para[position()=last()-1] 选择上下文节点的倒数第二个 para 孩子

  • child::para[position()>1] 选择上下文节点中除第一个以外所有的 para 孩子

  • following-sibling::chapter[position()=1] 选择上下文节点的下一个 chapter 兄弟

  • preceding-sibling::chapter[position()=1] 选择上下文节点的前一个 chapter 兄弟

  • /descendant::figure[position()=42] 选择文档中第四十二个 figure 元素

  • /child::doc/child::chapter[position()=5]/child::section[position()=2] 选择文档元素 doc 的第五个 chapter 的第二个 section

  • child::para[attribute::type='warning"] 选择的上下文节点中有属性 type 且值为 warningpara 孩子

  • child::para[attribute::type='warning'][position()=5] 选择的上下文节点中所有的有属性 type 且值为 warningpara 孩子中第五个孩子

  • child::para[position()=5][attribute::type="warning"] 选择的上下文节点中第五个 para 孩子,如果该孩子有 type 属性且值为 warning 的话

  • child::chapter[child::title='Introduction'] 选择的上下文节点的 chapter 孩子,这些孩子有一个或一个以上字串值等於 Introductiontitle 孩子

  • child::chapter[child::title] 选择的上下文节点中有一个或一个以上 title 孩子的 chapter 孩子

  • child::*[self::chapter or self::appendix] 选择上下文节点的 chapterappendix 孩子

  • child::*[self::chapter or self::appendix][position()=last()] 选择上下文节点的最后一个 chapterappendix 孩子

地址路径有两种:相对的地址路径和绝对的地址路径。

相对的地址路径由以 / 分开的一个或多个地点步进序列组成。在相对地址路径中的步进是从左到右组成。每一步进依次选择相对於上下文节点的节点集。步进的初始的序列以如下所述的方式与后续的步进组成在一起。步进的初始的序列选择相对於上下文节点的节点集,该集合的每一节点成为后续步进的上下文节点。由步进确定的节点的集合是联合在一起的。由合成的步进确定的节点的集合也是这样的联合。例如,child::div/child::para 选择了上下文节点的所有 div 元素孩子的所有 para 元素孩子,或者换句话说,选择了上下文节点中所有有以 div 为父 para 元素孙子。

绝对的地址路径由 / 及紧随其后的作为可选项的一条相对地址路径组成。 / 本身选择以包含上下文节点的文档的根节点,如果它带着相对的地址路径,该地址路径选择的节点集合则由相对於包含上下文节点的文档的根节点相对地址路径来确定。

地址路径
[1]   LocationPath   ::=   RelativeLocationPath
| AbsoluteLocationPath
[2]   AbsoluteLocationPath   ::=   '/' RelativeLocationPath?
| AbbreviatedAbsoluteLocationPath
[3]   RelativeLocationPath   ::=   Step
| RelativeLocationPath '/' Step
| AbbreviatedRelativeLocationPath

2.1 地点步进

一个地点步进有三个部分:

  • 一个轴,它指定了地点步进选择的节点与上下文节点之间树状关系,

  • 一个节点测试,它指定地点步进选择的节点的节点类型以及节点扩展名扩展名,和

  • 零个或零个以上的判定词,它使用专有的表达式进一步细化地点步进选择的节点集合。

地点步进的句法是由两个冒号分开的轴名和节点测试,其后可跟随零个或零个以上在方括符内的表达式。例如,在 child::para[position()=1] 中,child 是轴名,para 是节点测试而 [position()=1] 则是判定词。

由地点步进选择的节点集合是源于从轴和节点测试产生初始的节点集合,然后再由各个判定词的依次过滤后的节点集合。

初始的节点集合的节点组成,这些节点与上下文节点关系由轴指定的,其节点类型及扩展名由节点测试指定。例如,地点步进 descendant::para 选择上下文节点的 para 元素子孙: descendant 指定在初始的节点集合中的那每一个节点都必须是该上下文的一个子孙; para 指定在初始的节点集合中的每一个节点都必须是 para 元素。2.2 轴说明了所有可能的轴。2.3 节点测试则说明了所有可能的节点测试。一些节点测试的含意依赖于轴。

初始的节点集合由第一个判定词过滤后产生一新的节点集合,新的节点集合再由第二个判定词进行过滤,如此一直下去。最后的节点集合是由地点步进选择的节点集合。轴影响在每个判定词中的表达式怎么被求值,并且因此判定词的语义定义与轴关于。参看2.4 判定词

地点步进
[4]   Step   ::=   AxisSpecifier NodeTest Predicate*
| AbbreviatedStep
[5]   AxisSpecifier   ::=   AxisName '::'
| AbbreviatedAxisSpecifier

2.2 轴

以下是可用到的轴:

  • child 轴包含上下文节点的孩子

  • descendant 轴包含上下文节点的子孙;子孙是一个孩子或一个孩子的一个孩子,等等,这样,子孙轴从来不包含属性或命名空间节点

  • parent 轴包含上下文节点的父,如果有的话

  • ancestor 轴包含上下文节点的祖先;上下文节点的祖先由上下文节点的父以及父的父等等组成;这样,祖先轴将总是包括根节点,除非上下文节点是根节点

  • following-sibling 轴包含上下文节点的所有在其后的兄弟,如果上下文节点是属性节点或命名空间节点,following-sibling 轴则为空

  • preceding-sibling 轴包含上下文节点的所有在其前的兄弟,如果上下文节点是属性节点或命名空间节点,preceding-sibling 轴则为空

  • following 轴包含在上下文节点所在的同一文档中,所有依照文档顺序在上下文节点后的节点,但排除所有的子孙,也排除属性节点以及命名空间节点

  • preceding 轴包含在上下文节点所在的同一文档中,所有依照文档顺序在上下文节点前的节点,但排除所有的子孙,也排除属性节点以及命名空间节点

  • attribute 轴包含上下文节点的属性,除非上下文节点是元素,该轴将为空

  • namespace 轴包含上下文节点的命名空间节点,除非上下文节点是元素,该轴将为空

  • self 轴只是包含上下文节点自己

  • descendant-or-self 轴包含上下文节点和上下文节点的子孙

  • ancestor-or-self 轴包含上下文节点和上下文节点的祖先;这样,该轴将总是包括根节点

注意:

ancestordescendantfollowingpreceding 以及 self 轴划分了一个文档(忽略属性和命名空间节点):他们相互不重叠,而且他们组在一起则包含了文档所有的节点。

[6]   AxisName   ::=   'ancestor'
| 'ancestor-or-self'
| 'attribute'
| 'child'
| 'descendant'
| 'descendant-or-self'
| 'following'
| 'following-sibling'
| 'namespace'
| 'parent'
| 'preceding'
| 'preceding-sibling'
| 'self'

2.3 节点测试

定义:每个轴都有一个基本节点类型。如果轴能包含元素,基本的节点类型则是元素;否则,它的类型是轴能包含的节点的类型。]因此,

对於属性轴来说,基本的节点类型是属性。
对於命名空间轴,基本的节点类型是命名空间。
对於其它的轴,基本的节点类型是元素。

当且仅当节点的类型(参看5 数据模型)是基本类型且扩展名等於由 QName 指定的扩展名时,为 QName 节点测试才为真。例如,child::para 选择了上下文节点的 para 元素孩子,如果上下文节点没有 para 孩子,它将选择节点的一个空集合;attribute::href 选择了上下文节点的 href 属性,如果上下文节点没有 href 属性,它将选择节点的一个空集合。

使用来自表达式的上下文的命名空间声明,在节点测试里的 QName 可扩展成扩展名。这与在起始及结束标签中元素类型名称的扩展方法一样,除了缺省的 xmlns 命名空间申明无须使用外:如果 QName 没有前缀,则命名空间 URI 为空 (这与属性名字扩展的方法一样)。如果 QName 有前缀,而表达式上下文中却没有命名空间声明,则是一个错误。

对於基本节点类型的任何节点,节点测试 * 都为真。例如,child::* 将选择上下文的所有的元素孩孩子,而 attribute::* 将选择上下文节点的所有的属性。

节点测试可以用格式 NCName:*。在这种情况下,前缀就以与 QName 一样的方法被扩展,即使用上下文命名空间声明。在表达式上下文的前缀如果没有命名空间声明,则是一个错误。不论名字的局域部分,对於基本类型的任何节点,如果其扩展名有命名空间 URI 将其前缀扩展,节点测试永为真。

对於任何正文节点,节点测试 text() 为真。例如,child::text() 将选择上下文节点的正文节点孩子。同样,对於注释节点,节点测试 comment() 为真;对於处理指令,节点测试 processing-instruction() 为真; processing-instruction() 测试可以有一个字面量 Literal 的参数,在这种情况下,对於所有的处理指令,如指令名与字面量值 Literal 相等,其值为真。

对於任何节点,无论其类型,节点测试 node() 为真。

[7]   NodeTest   ::=   NameTest
| NodeType '(' ')'
| 'processing-instruction' '(' Literal ')'

2.4 判定词

一个轴不是前进轴就是倒转轴。前进轴是依文本顺序在任何时候都仅仅包含上下文节点或在上下文节点以后的节点的轴。倒转轴是依文本顺序在任何时候都仅仅包含上下文节点或在文档顺序在上下文节点前的节点的轴。因此,ancestorancestor-or-selfprecedingpreceding-sibling 轴是倒转轴;所有的其余的轴都是前进轴。由於 self 轴总是至多包含一个节点,它是前进轴或是倒转轴都不造成任何差别。轴的节点集合的成员的[定义邻近位置对前进轴是按文档顺序的节点集合是节点的位置,对倒转轴是按文档反序的节点集合是节点的位置。第一个的位置是1。]

判定词依照轴过滤节点集合来生成新的节点集合。对於被过滤的节点集合里的每节点,PredicateExpr 将该节点作为上下文节点来求值,以节点集合的节点数为上下文大小,以依照在节点集合中节点的邻近位置为上下文位置,如果对节点 PredicateExpr 的求值为真,新的节点集合就包括该节点;否则就不包括。

PredicateExpr 求值是通过先求 Expr 的值并把结果转换成布尔值而来的。如果结果是一数字且该数字与上下文位置相等,结果将被转变为真;否则为假。如果结果不是一个数字,然后结果将被变换成好像调用过函数 boolean 后的结果。这样地址路径 para[3] 等价 para[position()=3]

判定词(Predicates)
[8]   Predicate   ::=   '[' PredicateExpr ']'
[9]   PredicateExpr   ::=   Expr

2.5 缩简句法

这是一些使用缩简句法的地址路径例子:

  • para 选择上下文节点的 para 元素孩子

  • * 选择上下文节点的所有的元素孩子

  • text() 选择上下文节点的所有的正文节点孩子

  • @name 选择上下文节点的 name 属性

  • @* 选择上下文节点的所有的属性

  • para[1] 选择上下文节点的第一个 para 孩子

  • para[last()] 选择上下文节点的最后一个 para 孩子

  • */para 选择上下文节点的所有的 para 孙子

  • /doc/chapter[5]/section[2] 选择doc的第五个 chapter 的第二个 section

  • chapter//para 选择上下文节点的 chapter 元素孩子的所有 para 元素子孙

  • //para 选择文档根的所有的 para 子孙,也就是选择上下文节点所在的文档中所有的 para 元素

  • //olist/item 选择上下文节点所在的文档中所有的以 olist 为父的 item 元素

  • . 选择上下文节点

  • .//para 选择上下文节点的 para 元素子孙

  • .. 选择上下文节点的父

  • ../@lang 选择上下文节点的父的 lang 属性

  • para[@type="warning"] 选择的上下文节点的所有的有属性 type 且值为 warningpara 孩子

  • para[@type="warning"][5] 选择的上下文节点的所有的有属性 type 且值为 warningpara 孩子中的第五个

  • para[5][@type="warning"] 选择的上下文节点的第五个 para 孩子如果该节点有属性 type 且值为 warning 的话

  • chapter[title="Introduction"] 选择上下文节点的 chapter 孩子如果它有一个或多个 title 孩子且字串值Introduction

  • chpater[title] 选择的上下文节点中有一个或一个以上 title 孩子的 chpater 孩子

  • employee[@secretary and @assistant] 选择上下文节点的所有既有 secretary 属性又有 assistant 属性的 employee 孩子

最重要的缩写是 child:: 能从地点步进省略掉。实际效果上,child 是缺省轴。例如,地址路径 div/parachild::div/child::para 的缩写。

属性也有缩写形式: attribute:: 能被缩写成 @。例如,地址路径 para[@type="warning"]child::para[attribute::type="warning"] 的缩写,也就是选择有 type 属性且属性值为 warningpara 孩子。

///descendant-or-self::node()/ 的缩写。例如,//para/descendant-or-self::node()/child::para 的缩写,因此选择文档中所有的 para 元素(即使 para 元素是文档元素,也会被 //para 所选择,因为文档元素是根节点的孩子); div//paradiv/descendant-or-self::node()/child::para 的缩写,因此将选择 div 孩子的所有 para 子孙。

注意:

地址路径 //para[1] 与地址路径 /descendant::para[1] 的含意不一样,后者选择第一个 para 元素子孙,前者选择是他们的父的第一 para 孩子的所有的子孙 para 元素。

地点路进 .self::node() 的缩写。这与 // 一起使用特别有用。例如,地址路径 .//paraself::node()/descendant-or-self::node()/child::para 的缩写,因此将选择上下文节点的所有的 para 子孙元素。

同样,地址路径 ..parent::node() 的缩写。例如,../titleparent::node()/child::title 的缩写因此这将选择上下文节点的父的 title 孩子。

缩写
[10]   AbbreviatedAbsoluteLocationPath   ::=   '//' RelativeLocationPath
[11]   AbbreviatedRelativeLocationPath   ::=   RelativeLocationPath '//' Step
[12]   AbbreviatedStep   ::=   '.'
| '..'
[13]   AbbreviatedAxisSpecifier   ::=   '@'?

3 表达式

3.1 基础

VariableReference 求值成变量名是绑定到在上下文中变量绑定的集合。如果变量名没有与在上下文中变量绑定的集合中的变量绑定在一起,则是一个错误。

括号可以用于分组。

[14]   Expr   ::=   OrExpr
[15]   PrimaryExpr   ::=   VariableReference
| '(' Expr ')'
| Literal
| Number
| FunctionCall