XPATH 1.0推荐标准摘译(第一部分)

1 简介

XPath 是为XSLTXPointer 重叠的部分功能提供通用的语法和语义而设计的,主要目标是寻址XML 文档的一部分,并为此提供了处理字符串、数字和布尔值的基本工具。XPath 采用一种紧凑的非XML 语法,以便在URIXML 属性值中使用。XPath 操作抽象的、逻辑的XML 文档结构,而不是表层语法。XPath 使用类似URL 路径的形式导航XML 层次结构,并因此而得名。

除了定位之外,XPath 的一个子集还用于匹配,这种用法在XSLT 中定义。

XPath XML 文档建模为节点树。节点分为元素节点、属性节点和文本节点等不同类型。XPath 定义了计算各种节点字符串值( string-value )的方法。有的节点还有名字。XPath 完全支持XML 名称空间 [XML Names] 。因此节点名称分为本地和名称空间URI (允许为空)两部分,称为扩展名( expanded-name )。

XPath 的基本语法构造是表达式。表达式和生成式 Expr 匹配。表达式的求值结果是一个对象,可以是下列四种基本类型之一:节点集(没有重复的无序节点集合)、布尔值、数字(浮点数)、字符串(UCS 字符序列。

表达式求值依赖于上下文,上下文如何确定由XSLTXPointer 定义。上下文包括:上下文节点、两个正整数(上下文位置和上下文大小)、变量绑定、函数库、作用域内的名称空间声明。

上下文位置小于等于上下文大小。

变量绑定由变量名到变量值的映射组成,除了上述四种类型之外,也允许其他类型的变量值。

函数库包括函数名到函数的映射,每个函数允许个数不限的参数和一个返回值。本文定义了所有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]

选择文档中第42figure 元素

/child::doc/child::chapter[position()=5]/child::section[position()=2]

选择doc 元素第五个chapter 孩子的第二个section

child::para[attribute::type="warning"]

选择上下文节点属性typewarning 的所有para 孩子

child::para[attribute::type='warning'][position()=5]

选择属性typewarning 的第五个para 孩子

child::para[position()=5][attribute::type="warning"]

选择第五个para 孩子并要求该元素属性typewarning

child::chapter[child::title='Introduction']

选择至少有一个title 孩子且其字符串值为Introductionchapter 孩子

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 元素孩子。

绝对位置路径以/ 开始,/ 选择文档根节点,其后的相对位置路径则以根节点作为上下文节点。

位置路径

[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 descendantfollowingprecedingself 轴(不考虑属性和名称空间节点)将文档划分成互不交叉的几部分

[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 谓词

轴分为前向轴和逆向轴。按照文档序指向上下文节点及其后节点的轴为前向轴,指向上下文节点之前节点的轴为逆向轴。Ancestorancestor-or-self precedingpreceding-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"]

属性typewarning 的所有para 孩子

para[@type="warning"][5]

第五个属性typewarningpara 孩子

para[5][@type="warning"]

第五个para 孩子,并要求其type 属性值为warning

chapter[title="Introduction"]

至少有一个title 孩子的字符串值为Introductionchapter 孩子

chapter[title]

至少包含一个title 孩子的chapter 孩子

employee[@secretary and @assistant]

同时具有secretaryassistant 属性的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::paradiv//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

   ::=   

'@'?

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值