XPath 简介

XPath 简介

什么是XPath

XPath

XPath路径表达式

XPath使用路径表达式来选取XML文档中的节点或者节点集,这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。

XPath节点

在XPath中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。XML文档是被作为节点树来对待的,树的根被称为文档节点或者根节点。

示例:

<?xml version="1.0" encoding="ISO-8859-1"?>

<bookstore>
    <book>
        <title lang="en">Harry Potter</title>
        <author>J K. Rowling</author>
        <year>2005</year>
        <price>29.99</price>
    </book>
</bookstore>

上面的XML文档中的节点例子:

<bookstore> (文档节点)  
<author>J K. Rowling</author> (元素节点)    
lang="en" (属性节点)

节点关系

父(Parent)

每个元素以及属性都有一个父节点。

在上面的例子中,book 元素是 title、author、year 以及 price 元素的父节点。

子(Children)

元素节点可有零个、一个或多个子节点。

在上面的例子中,title、author、year 以及 price 元素都是 book 元素的子节点。

同胞(Sibling)

拥有相同的父的节点。

在上面的例子中,title、author、year 以及 price 元素都是同胞。

先辈(Ancestor)

某节点的父、父的父,等等。

在上面的例子中,title 元素的先辈有 book 元素和 bookstore 元素。

后代(Descendant)

某个节点的子,子的子,等等。

在上面的例子中,bookstore 的后代是 book、title、author、year 以及 price 元素。

XPath语法

选取节点

XPath使用路径表达式在XML文档中选取节点。节点是通过沿着路径或者step来选取的。

下面列出了最有用的路径表达式:

表达式描述
nodename选取此节点的所有子节点。
/从根节点选取。
//从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
.选取当前节点。
..选取当前节点的父节点。
@选取属性。

在下面的表格中,我们已列出了一些路径表达式以及表达式的结果:

路径表达式结果
bookstore选取 bookstore 元素的所有子节点。
/bookstore选取根元素 bookstore。
注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
bookstore/book选取属于 bookstore 的子元素的所有 book 元素。
//book选取所有 book 子元素,而不管它们在文档中的位置。
bookstore//book选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
//@lang选取名为 lang 的所有属性。

谓语(Predicates)

谓语用来查找某个特定的节点或者包含某个指定的值的节点,谓语被嵌在方括号中。

在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:

路径表达式结果
/bookstore/book[1]选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()]选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1]选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position()<3]选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//title[@lang]选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang=’eng’]选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
/bookstore/book[price>35.00]选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]/title选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。

选取未知节点

XPath通配符可用来选取未知的XML元素。

通配符描述
*匹配任何元素节点。
@*匹配任何属性节点。
node()匹配任何类型的节点。

在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

路径表达式结果
/bookstore/*选取 bookstore 元素的所有子元素。
//*选取文档中的所有元素。
//title[@*]选取所有带有属性的 title 元素。

选取若干路径

通过在路径表达式中使用”|”运算符,可以选取若干个路径。

在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

路径表达式结果
//book/title | //book/price选取 book 元素的所有 title 和 price 元素。
//title | //price选取文档中的所有 title 和 price 元素。
/bookstore/book/title | //price选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。

XPath轴

轴可定义相对于当前节点的节点集。

轴名称结果
ancestor选取当前节点的所有先辈(父、祖父等)。
ancestor-or-self选取当前节点的所有先辈(父、祖父等)以及当前节点本身。
attribute选取当前节点的所有属性。
child选取当前节点的所有子元素。
descendant选取当前节点的所有后代元素(子、孙等)。
descendant-or-self选取当前节点的所有后代元素(子、孙等)以及当前节点本身。
following选取文档中当前节点的结束标签之后的所有节点。
namespace选取当前节点的所有命名空间节点。
parent选取当前节点的父节点。
preceding选取文档中当前节点的开始标签之前的所有节点。
preceding-sibling选取当前节点之前的所有同级节点。
self选取当前节点。

XPath 运算符

下面列出了可用在 XPath 表达式中的运算符:

运算符描述实例返回值
计算两个节点集//book | //cd返回所有拥有 book 和 cd 元素的节点集
+加法6 + 410
-减法6 - 42
*乘法6 * 424
div除法8 div 42
=等于price=9.80如果 price 是 9.80,则返回 true。如果 price 是 9.90,则返回 false。
!=不等于price!=9.80如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。
<小于price<9.80如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。
<=小于或等于price<=9.80如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。
>大于price>9.80如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。
>=大于或等于price>=9.80如果 price 是 9.90,则返回 true。如果 price 是 9.70,则返回 false。
orprice=9.80 or price=9.70如果 price 是 9.80,则返回 true。如果 price 是 9.50,则返回 false。
andprice>9.00 and price<9.90如果 price 是 9.80,则返回 true。如果 price 是 8.50,则返回 false。
mod计算除法的余数5 mod 21

完整示例

使用dom4j解析以下xml文件:

<?xml version="1.0" encoding="ISO-8859-1"?>

<bookstore>
    <book category="COOKING">
        <title lang="en">Everyday Italian</title>
        <author>Giada De Laurentiis</author>
        <year>2005</year>
        <price>30.00</price>
    </book>
    <book category="CHILDREN">
        <title lang="en">Harry Potter</title>
        <author>J K. Rowling</author>
        <year>2005</year>
        <price>29.99</price>
    </book>
    <book category="WEB">
        <title lang="en">XQuery Kick Start</title>
        <author>James McGovern</author>
        <author>Per Bothner</author>
        <author>Kurt Cagle</author>
        <author>James Linn</author>
        <author>Vaidyanathan Nagarajan</author>
        <year>2003</year>
        <price>49.99</price>
    </book>
    <book category="WEB">
        <title lang="en">Learning XML</title>
        <author>Erik T. Ray</author>
        <year>2003</year>
        <price>39.95</price>
    </book>
</bookstore>

Java代码:

import java.io.File;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Text;
import org.dom4j.io.SAXReader;

/**
 * 使用XPath查找节点
 * 
 * @author 小明
 *
 */
public class XPathTest {

    public static void search() throws Exception {
        // 创建SAXReader对象
        SAXReader reader = new SAXReader();
        // 创建Document对象
        Document document = reader.read(new File("books.xml"));

        /* 查找所有的书籍的title */
        List nodes = document.selectNodes("//book/title");
        // 迭代
        Iterator it = nodes.iterator();
        System.out.println("所有的书籍的title:");
        while (it.hasNext()) {
            Element item = (Element) it.next();
            System.out.println(item.getText());
        }

        /* 查找所有书籍的price的文本 */
        nodes = document.selectNodes("//book/price/text()");
        // 迭代
        it = nodes.iterator();
        System.out.println("所有书籍的price的文本:");
        while (it.hasNext()) {
            Text item = (Text) it.next();
            System.out.println(item.getText());
        }

        /* 查找所有 category="WEB" 的 book 节点,输出它们的 title */
        nodes = document.selectNodes("//book[@category='WEB']/title");
        // 迭代
        it = nodes.iterator();
        System.out.println("查找所有 category='WEB' 的 book 节点,输出它们的 title:");
        while (it.hasNext()) {
            Element item = (Element) it.next();
            System.out.println(item.getText());
        }

        /* 查找所有 2005 年出版的 book 的 title */
        nodes = document.selectNodes("//book[year=2005]/title");
        it = nodes.iterator();
        System.out.println("查找所有 2005 年出版的 book 的 title:");
        while (it.hasNext()) {
            Element item = (Element) it.next();
            System.out.println(item.getText());
        }

        /* 查找第一本 category='WEB' 的 book 的 title */
        nodes = document.selectNodes("//book[@category='WEB'][1]/title");
        it = nodes.iterator();
        System.out.println("查找第一本 category='WEB' 的 book 的 title:");
        while (it.hasNext()) {
            Element item = (Element) it.next();
            System.out.println(item.getText());
        }

        /* 查找price 大于 35.00 的book 的 title 和 category属性 */
        nodes = document
                .selectNodes("//book[price>35.00]/title|//book[price>35.00]/@category");
        it = nodes.iterator();
        System.out.println("查找price 大于 35.00 的book 的 title 和 category属性:");
        while (it.hasNext()) {
            Object obj = it.next();
            if (obj instanceof Element) { // title为元素
                Element item = (Element) obj;
                System.out.println(item.getText());
            } else if (obj instanceof Attribute) { // category为属性
                Attribute attr = (Attribute) obj;
                System.out.print(attr.getValue() + " : ");
            }
        }
    }

    public static void main(String[] args) throws Exception {
        search();
    }
}

运行结果:

所有的书籍的title:
Everyday Italian
Harry Potter
XQuery Kick Start
Learning XML
所有书籍的price的文本:
30.00
29.99
49.99
39.95
查找所有 category='WEB' 的 book 节点,输出它们的 title:
XQuery Kick Start
Learning XML
查找所有 2005 年出版的 book 的 title:
Everyday Italian
Harry Potter
查找第一本 category='WEB' 的 book 的 title:
XQuery Kick Start
查找price 大于 35.00 的book 的 title 和 category属性:
WEB : XQuery Kick Start
WEB : Learning XML
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值