概述
1 简介
XPath 是为XSLT 和XPointer 重叠的部分功能提供通用的语法和语义而设计的,主要目标是寻址XML 文档的一部分,并为此提供了处理字符串、数字和布尔值的基本工具。XPath 采用一种紧凑的非XML 语法,以便在URI 和XML 属性值中使用。XPath 操作抽象的、逻辑的XML 文档结构,而不是表层语法。XPath 使用类似URL 路径的形式导航XML 层次结构,并因此而得名。
除了定位之外,XPath 的一个子集还用于匹配,这种用法在XSLT 中定义。
XPath 将XML 文档建模为节点树。节点分为元素节点、属性节点和文本节点等不同类型。XPath 定义了计算各种节点字符串值( string-value )的方法。有的节点还有名字。XPath 完全支持XML 名称空间 [XML Names] 。因此节点名称分为本地和名称空间URI (允许为空)两部分,称为扩展名( expanded-name )。
XPath 的基本语法构造是表达式。表达式和生成式 Expr 匹配。表达式的求值结果是一个对象,可以是下列四种基本类型之一:节点集(没有重复的无序节点集合)、布尔值、数字(浮点数)、字符串(UCS 字符序列。
表达式求值依赖于上下文,上下文如何确定由XSLT 和XPointer 定义。上下文包括:上下文节点、两个正整数(上下文位置和上下文大小)、变量绑定、函数库、作用域内的名称空间声明。
上下文位置小于等于上下文大小。
变量绑定由变量名到变量值的映射组成,除了上述四种类型之外,也允许其他类型的变量值。
函数库包括函数名到函数的映射,每个函数允许个数不限的参数和一个返回值。本文定义了所有XPath 实现必须指出的核心函数库 [4 Core Function Library ] 。这些核心函数的参数和返回值都属于上述四种基本数据类型,扩展函数允许操作其他类型。
名称空间声明定义了从前缀到名称空间URI 的映射。
子表达式的变量绑定、函数库和名称空间声明和父表达式一样,但上下文节点、上下文位置和上下文大小可能不同。有些表达式会改变上下文节点,只有谓词 [2.4 Predicates ] 改变上下文位置和大小。
XPath 表达式通常出现在XML 属性中,下述文法适用于XML 规范化之后的属性值。在表达式中,字面字符串用单引号或双引号括起来,为了避免与包围属性值的引号区分,可采用字符引用(" 或' ),或者交叉使用两种引号。
最重要的一类表达式是位置路径。位置路径相对于当前节点选择一组节点。位置路径表达式的结果是有一个节点集。位置路径可以递归包含其他表达式对节点集进行过滤。位置路径匹配生成式 LocationPath 。
下述文法中,非终止符 QName 和 NCName 在 [XML Names] 中定义, S 在 [XML] 中定义。文法采用的EBNF 记号与 [XML] 相同(除了首字母大写的符号以外)。
解析的时候,首先将表达式字符串分解成不同的记号token ,忽略记号之间的空白字符,记号的处理参见3.7 。
2 位置路径
位置路径是XPath 中最重要的结构。位置路径有两种形式,一种清晰易懂但比较啰嗦,另一种更简洁。下面是完整形式的位置路径的一些例子:
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 | 选择上下文节点的所有para 元素后代,如果上下文节点是para 元素,也包括它自身 |
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] | 选择文档中第42 个figure 元素 |
/child::doc/child::chapter[position()=5]/child::section[position()=2] | 选择doc 元素第五个chapter 孩子的第二个section |
child::para[attribute::type="warning"] | 选择上下文节点属性type 为warning 的所有para 孩子 |
child::para[attribute::type='warning'][position()=5] | 选择属性type 为warning 的第五个para 孩子 |
child::para[position()=5][attribute::type="warning"] | 选择第五个para 孩子并要求该元素属性type 为warning |
child::chapter[child::title='Introduction'] | 选择至少有一个title 孩子且其字符串值为Introduction 的chapter 孩子 |
child::chapter[child::title] | 选择至少有一个title 孩子的chapter 孩子 |
child::*[self::chapter or self::appendix] | 选择所有chapter 和appendix 孩子 |
child::*[self::chapter or self::appendix][position()=last()] | 选择最后一个chapter 或appendix 孩子 |
位置路径分为相对位置路径和绝对位置路径。相对位置路径由一系列用/ 分隔的位置步组成,相对位置路径中的位置步从左向右结合。每一步都选择一组节点。第一个位置步相对于上下文节点选择一组节点,然后把这些节点作为下一个位置步的上下文节点进一步选择,将得到的节点集取并,以此类推。比如,child::div/child::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] 是谓词。首先根据轴和节点测试选择一个初始节点集,然后用谓词进一步筛选。初始节点集中的节点和上下文节点之间具有轴所指定的关系(父子兄弟),节点测试所指定的节点类型和扩展名(文本节点都是匿名节点,用text() 指定;元素节点则依赖于元素名;属性节点通过轴来选择)。比如位置步descendant::para 选择上下文节点的para 元素后代:descendant 指定初始节点集中的节点必须是上下文的后代;para 要求初始节点集中的节点必须是名为para 的元素。初始节点集根据第一个谓词过滤后得到一个新的节点集,然后根据第二个谓词过滤得到另一个新的节点集,依次类推。谓词的语义和轴有关。
位置步
[4] | Step | ::= | AxisSpecifier NodeTest Predicate * | |
| AbbreviatedStep | ||||
[5] | AxisSpecifier | ::= | AxisName '::' | |
| AbbreviatedAxisSpecifier |
2.2 轴
Child | 上下文节点的孩子 |
Descendant | 上下文节点的后代,不包括属性或名称空间节点 |
Parent | 上下文节点的父节点,根节点没有父节点 |
Ancestor | 上下文节点的祖先,必然包含根节点(处分上下文节点是根节点) |
following-sibling | 上下文节点的后兄弟节点,属性节点和名称空间节点没有后兄弟节点 |
preceding-sibling | 上下文节点的前兄弟节点,属性节点和名称空间节点没有前兄弟节点 |
following | 按照文档序上下文节点之后的所有节点,不包括上下文节点的后代,也不包括属性和名称空间节点 |
preceding | 按照文档序上下文节点之前的所有节点,不包括上下文节点的祖先,也不包括属性和名称空间节点 |
attribute | 上下文节点的属性,仅用于元素,否则为空节点集 |
namespace | 上下文节点的名称空间节点,仅用于元素 |
self | 上下文节点自身 |
descendant-or-self | 上下文节点及其后代 |
ancestor-or-self | 上下文节点及其最先,必然包括根节点 |
Ancestor 、descendant 、following 、preceding 和self 轴(不考虑属性和名称空间节点)将文档划分成互不交叉的几部分
轴
[6] AxisName ::= 'ancestor'| 'ancestor-or-self'| 'attribute'| ‘child' |'descendant' | 'descendant-or-self'| 'following'| 'following-sibling'| 'namespace' | 'parent' | 'preceding' | 'preceding-sibling' | 'self' |
2.3 节点测试
每个轴都有一个主节点类型。如果允许包含元素,则主节点类型就是元素,否则为该轴所能包含的节点类型。因此,轴attribute 的主节点类型为属性,namespace 轴的主节点类型为名称空间,其他轴的主节点类型都是元素。
如果节点测试为QName ,则节点类型必须是轴指定的主节点类型,并且扩展名和QName 指定的扩展名相同。比如child::para 选择para 孩子元素, attribute::href 选择href 属性。节点测试中的QName 使用上下文中的名称空间声明扩展成expanded-name ,但是与开始/ 结束标签中元素名扩展不同的是不使用xmlns 声明的默认名称空间,就是说如果QName 没有前缀,则名称空间URI 为空(类似于属性名扩展)。
节点测试* 选择主节点类型的所有节点,比如child::* 选择上下文节点的所有元素孩子,attribute::* 选择所有属性。
如果节点测试的形式为 NCName :* ,选择属于NCName 名称空间URI 的所有主节点类型的节点。
节点测试text() 选择所有文本节点,comment() 选择注释节点,processing-instruction() 选择处理指令节点。processing-instruction() 测试允许带一个参数,指定处理指令名称。
节点测试node() 选择任何类型的节点。
[7] | NodeTest | ::= | NameTest | |
| NodeType '(' ')' | ||||
| 'processing-instruction' '(' Literal ')' |
2.4 谓词
轴分为前向轴和逆向轴。按照文档序指向上下文节点及其后节点的轴为前向轴,指向上下文节点之前节点的轴为逆向轴。Ancestor 、ancestor-or-self 、 preceding 和preceding-sibling 轴是逆向轴,其他都是前向轴。节点集成员的位置,对于前向轴来说按照文档顺序计算,对于逆向轴来说则是按照反文档顺序计算。初始位置为1 。
使用谓词过滤节点集时,以其中的每个节点作为上下文节点计算 PredicateExpr ,以节点集中节点的个数作为上下文大小,以该节点在集合中的位置作为上下文位置,如果 PredicateExpr 结果为true ,则保留在新结果集中,否则去掉。
计算 PredicateExpr 的时候,首先计算 Expr 然后将结果转化为布尔值。如果结果是数字,且这个数字等于上下文位置,则转化为True ,否则为false ;如果不是数字则按照Boolean 函数的定义转换。因此位置路径para[3] 相当于para[position()=3] 。
谓词
[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 元素 |
//olist/item | 文档中所有以olist 作为父节点的所有item 元素 |
. | 上下文节点 |
.//para | 上下文节点的所有para 元素后代 |
.. | 上下文节点的父节点 |
../@lang | 父节点的lang 属性 |
para[@type="warning"] | 属性type 为warning 的所有para 孩子 |
para[@type="warning"][5] | 第五个属性type 为warning 的para 孩子 |
para[5][@type="warning"] | 第五个para 孩子,并要求其type 属性值为warning |
chapter[title="Introduction"] | 至少有一个title 孩子的字符串值为Introduction 的chapter 孩子 |
chapter[title] | 至少包含一个title 孩子的chapter 孩子 |
employee[@secretary and @assistant] | 同时具有secretary 和assistant 属性的employees 孩子 |
缩写形式最重要的是位置步中可以省略child:: ,实际上就相当于把child 作为默认轴,比如div/para 就是child::div/child::para 的缩写。
属性轴attribute:: 可简写为@ ,比如位置路径para[@type="warning"] 是child::para[attribute::type="warning"] 的简写。
// 是/descendant-or-self::node()/ 的缩写,如//para 的完整形式为/descendant-or-self::node()/child::para ,div//para 的完整形式为div/descendant-or-self::node()/child::para 。
需要注意的是,位置路径//para[1] 和/descendant::para[1] 的含义不同。前者的完整形式为/descendent-or-self::node()/child::para[position()=1] ,初始节点集是文档中的所有节点,第二个地址步选择其中的para 元素,谓词筛选出的是在其父节点中出现的第一个para 孩子,因此可能有多个。后者选择第一个para 元素后代。
地址步. 是self::node() 的简写,与// 连用时非常方便,比如.//para 的完整形式为self::node()/descendant-or-self::node()/child::para 。
位置步.. 是parent::node() 的简写,比如../title 选择父节点的所有title 孩子。
缩写
[10] | AbbreviatedAbsoluteLocationPath | ::= | '//' RelativeLocationPath | |
[11] | AbbreviatedRelativeLocationPath | ::= | RelativeLocationPath '//' Step | |
[12] | AbbreviatedStep | ::= | '.' | |
| '..' | ||||
[13] | AbbreviatedAxisSpecifier | ::= | '@'? |
最后
以上就是温柔服饰为你收集整理的XPATH 1.0推荐标准摘译(第一部分)的全部内容,希望文章能够帮你解决XPATH 1.0推荐标准摘译(第一部分)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复