XPath详细介绍
XPath是XML路径语言,W3C的一个标准。它最主要的目的是为了在XML1.0或XML1.1文档节点树中定位节点所设计。目前 XPath1.0和XPath2.0两个版本。其中XPath1.0是1999年成为W3C标准,而XPath2.0标准的确立是在2007年。
XPath是一种表达式语言,它的返回值可能是节点,节点集合,原子值,以及节点和原子值的混合等。XPath2.0是XPath1.0的超集,它 是对XPath1.0的扩展,它可以支持更加丰富的数据类型,并且XPath2.0保持了对XPath1.0的相对很好的向后兼容性,几乎所有的 XPath2.0的返回结果都可以和XPath1.0保持一样。另外XPath2.0也是XSLT2.0和XQuery1.0的用于查询定位节点的主表达 式语言。
在学习XPath之前你应该对XML的节点,元素,属性,原子值(文本),处理指令,注释,根节点(文档节点),命名空间以及对节点间的关系如:父 (Parent),子(Children),兄弟(Sibling),先辈(Ancestor),后代(Descendant)等概念有所了解。这里不在 说明。
路径表达式语法
-
路径 = 相对路径 | 绝对路径
-
XPath路径表达式 = 步进表达式 | 相对路径 “/” 步进表达式。
-
步进表达式 = 轴 节点测试 谓词
说明:1. 其中轴表示步进表达式选择的节点和当前上下文节点间的树状关系(层次关系),节点测试指定步进表达式选择的节点名称扩展名,谓词即相当于过滤表达式以进一 步过滤细化节点集。2. 谓词可以是0个或多个。多个谓词用逻辑操作符and,or连接。取逻辑非用not()函数。
请看一个典型的XPath查询表达式:/messages/message//child::node()[@id=0], 其中/messages/message是路径(绝对路径以“/”开始),child::是轴表示在子节点下选择,node()是节点测试表示选择所有的 节点。[@id=0]是谓词,表示选择所有有属性id并值为0的节点。
相对路径与绝对路径
如果“/”处在XPath表达式开头则表示文件根元素,(表达式中间作为分隔符用以分割每一个步进表达式)如:/messages/message /subject是一种绝对路径表示法,它表明是从文档根开始查找节点。假设当前节点是在第一个message节点(/messages /message[1]),则路径表达式subject(路径前没有“/”)这种表示法称为相对路径,表明从当前节点开始查找。
表达式上下文(Context)
上下文其实表示一种环境。以明确当前XPath路径表达式处在什么样的环境下执行。例如同样一个路径表达式处在对根节点操作的环境和处在对某一个特定子节点操作的环境下执行所获得的结果可能是完全不一样的。也就是说XPath路径表达式计算结果取决于它所处的上下文。
XPath上下文基本有以下几种:
-
当前节点(./):如./sender表达式选择当前节点下的sender节点集合(等同于下面所讲的“特定元素”,如:sender)
-
父节点(../):如../sender表示选择当前节点的父节点下的sender节点集合
-
根节点(/*):这里的*是代表所有节点,但是根元素只有一个,所以这里表示根节点。/*的返回结果和/messages返回的结果一样都是messages节点。
-
递归下降(//):如例 /messages//sender。从当前节点messages开始递归步进搜索当前节点下的所有子节点找到满足条件的节点sender集。
-
特定元素:如sender,表示选择当前节点下的sender节点集合,等同于(./sender)。
注意:在执行XPath时一定要注意上下文。即当前是在哪个节点下执行XPath表达式。这在XML的DOM中很重要。
谓词(筛选表达式)及轴的概念
XPath的谓词即筛选表达式,类似于SQL的where子句:
轴名称 |
结果 |
ancestor |
选取当前节点的所有先辈(父,祖父等) |
ancestor-or-self |
选取当前节点的所有先辈(父,祖父等)以及当前节点本身 |
attribute |
选取当前节点的所有属性 |
child |
选取当前节点的所有子元素 |
descendant |
选取当前节点的所有后代元素(子,孙等) |
descendant-or-self |
选取当前节点的所有后代元素(子,孙等)以及当前节点本身 |
following |
选取文档中当前节点的结束标签之后的所有节点。 |
namespace |
选取当前节点的所有命名空间节点 |
parent |
选取当前节点的父节点 |
preceding |
找到所有这个节点的父辈节点,顺序选择每个父辈节点前的所有同级节点。 |
self |
选取当前节点 |
运算符及特殊字符:
运算符/特殊字符 |
说明 |
/ |
此路径运算符出现在模式开头时,表示应从根节点选择 |
// |
从当前节点开始递归下降,此路径运算符出现在模式开头时,表示应用根节点递归下降 |
. |
当前上下文 |
.. |
当前上下文节点父级 |
* |
通配符,选择所有元素节点与元素名无关。(不包括文本,注释,指令等节点,如果也要包含这些节点请用node()函数) |
@ |
属性名的前缀 |
@* |
选择所有属性,与名称无关 |
: |
命名空间分隔符,将命名空间前缀与元素名或属性名分隔 |
() |
括号运算符(优先级最高),强制运算优先级 |
[] |
应用筛选模式(即谓词,包括“过滤表达式”和“轴(向前/向后)”) 另一种表示下票运算符,用于在集合中编制索引 |
| |
两个节点集合的联合,如://messages/message/to | //messages/message/cc |
- |
减法 |
div , |
浮点除法 |
and , or |
逻辑运算 |
mod |
求余 |
not() |
逻辑非 |
= |
等于 |
!= |
不等于 |
特殊比较运算符 |
< 或者 < <= 或者 <= > 或者 > >= 或者 >= 需要转义的时候必须使用转义的形式 |
常用表达式实例:
/ |
Document Root文档根 |
/* |
选择文档根下面的所有元素节点,即根节点(XML文档只有一个根节点) |
/node() |
根元素下所有的节点(包括文本节点,注释节点等) |
/text() |
查找文档根节点下的所有文本节点 |
/messages/message |
messages节点下的所有message节点 |
/messages/message[1] |
messages节点下的第一个message节点 |
/messages/message[1]/self::node() |
第一个message节点(self轴表示自身,node()表示选择所有节点) |
/messages/message[1]/node() |
第一个message节点下的所有子节点 |
/messages/message[1]/*[last()] |
每一个message节点的最后一个子节点 |
/messages/message[1]/[last()] |
Error,谓词前必须是节点或节点集 |
/messages/message[1]/node()[last()] |
第一个message节点的最后一个子节点 |
/messages/message[1]/text() |
每一个message节点下的所有文本节点 |
/messages/message[1]//text() |
第一个message节点下递归下降查找所有的文本节点(无限深度) |
/messages/message[1]/child::node() /messages/message[1]/node() /messages/message[position()=1]/mode() //message[@id=1]/node() |
第一个message节点下的所有子节点 |
//message[@id=1]//child:node() |
递归所有子节点(无限深度) |