使用xpath提取xml中的节点信息

类似于使用SQL从数据库从查询数据。XPath可以方便的在XML 文档中查找信息的语言,并在XML文档中对元素和属性进行遍历。XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取的。
虽然有很强的表达能力,XPath 并不是 Java 语言,事实上 XPath 不是一种完整的编程语言。有很多东西用 XPath 表达不出来,甚至有些查询也无法表达。幸运的是,可以把 XPath 结合到 Java 程序中,这样就能发挥两者的优势了:Java 做 Java 所擅长的,XPath 做 XPath 所擅长的。
在最初,Java 程序执行 XPath 查询所需要的应用程序编程接口(API)因形形色色的 XPath 引擎而各不相同。Xalan 有一种 API,Saxon 使用另一种,其他引擎则使用其他的 API。这意味着代码往往把您限制到一种产品上。最好能够试验具有不同性能特点的各种引擎,而不会带来不适当的麻烦或者重新编写代码。
幸运的是Java 5 推出了 javax.xml.xpath 包,提供一个引擎和对象模型独立的 XPath 库。这个包也可用于 Java 1.3 及以后的版本,但需要单独安装 Java API for XML Processing (JAXP) 1.3。Xalan 2.7 和 Saxon 8 以及其他产品包含了这个库的实现。

这里先简单介绍下xpath的基本语法,后面再举详细的例子。节点选取语法:

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

谓词(用来查找某个特定的节点或者包含某个指定的值的节点,通常使用在[]内)
[table]
|路径表达式|结果
|/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。
[/table]
节点通配符:
[table]
|通配符|描述
|*|匹配任何元素节点
|@*|匹配任何属性节点
|node()|匹配任何类型的节点
[/table]
路径组合表达式,组合多个路径表达式,扩大选择范围;例如:
//book/title | //book/price 选取所有 book 元素的 title 和 price 元素。

另外,关于xpath的轴和运算符这里就不再细说了,有兴趣的可以参看后面的参看资料。
下面给出一个实例,展示如何在java中使用xpath提取xml中的信息
xml文件test.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="zh">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>

提取xml文件中节点信息的java代码:

/**
* "/"表示绝对路径 <br/>
* "/AA" 所有根节点AA<br/>
* "/AA/BB" 所有根节点下的所有BB节点<br/>
*
* "//" 表示相对路径<br/>
* "//BBB" 表示所有的名字为BBB的节点<br/>
* "//DDD/BBB" 表示所有父节点为DDD的BBB节点<br/>
*
* "*" 表示选择所有由星号之前的路径所定位的元素<br/>
* "/AAA/CCC/DDD/*" 选择所有路径依附于/AAA/CCC/DDD的元素<br/>
* "//*" 选择所有元素
*
* "/AAA/BBB[1]" 选择AAA的第一个BBB子元素<br/>
* "/AAA/BBB[last()]" 选择AAA的最后一个BBB子元素<br/>
*
* "//@id" 选择所有的id属性<br/>
* "//BBB[@id]" 选择有id属性的BBB元素<br/>
* "//BBB[@name]" 选择有name属性的BBB元素<br/>
* "//BBB[@*]" 选择有任意属性的BBB元素<br/>
* "//BBB[not(@*)]" 选择没有属性的BBB元素<br/>
*
* "//BBB[@id='b1']" 选择含有属性id且其值为'b1'的BBB元素<br/>
* "//BBB[@name='bbb']" 选择含有属性name且其值为'bbb'的BBB元素<br/>
* "//BBB[normalize-space(@name)='bbb']"
* 选择含有属性name且其值(在用normalize-space函数去掉前后空格后)为'bbb'的BBB元素<br/>
*
* "//*[count(BBB)=2]" 选择含有2个BBB子元素的元素<br/>
* "//*[count(*)=2]" 选择含有2个子元素的元素<br/>
* "//*[name()='BBB']" 选择所有名称为BBB的元素(这里等价于//BBB)<br/>
* "//*[starts-with(name(),'B')]" 选择所有名称以"B"起始的元素<br/>
* "//*[contains(name(),'C')]" 选择所有名称包含"C"的元素<br/>
*
* "//CCC | //BBB" 选择所有的CCC和BBB元素<br/>
* "/AAA/EEE | //BBB" 选择所有的BBB元素和所有是AAA的子元素的EEE元素<br/>
*/

InputSource inputSource = new InputSource(new FileInputStream("test.xml"));
XPathFactory factory = XPathFactory.newInstance();
XPath xPath = factory.newXPath();
XPathExpression expression = xPath.compile("//book/title[@lang=\"en\"]");
NodeList list = (NodeList) expression.evaluate(inputSource, XPathConstants.NODESET);
for (int i = 0; i < list.getLength(); i++) {
Node node = list.item(i);
System.out.println(node.getNodeName());
}

解析的步骤如下:
1、获取xml文件

InputSource inputSource = new InputSource(new FileInputStream("test.xml"));
//或者使用DOM解析
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse("test.xml");

2、接下来创建 XPathFactory:

XPathFactory factory = XPathFactory.newInstance();

3、然后使用这个工厂创建 XPath 对象:

XPath xPath = factory.newXPath();

4、使用XPath 对象编译 XPath 表达式:

XPathExpression expression = xPath.compile("//book/title[@lang=\"en\"]");

5、使用表达式的evaluate(),并处理结果:

NodeList list = (NodeList) expression.evaluate(inputSource, XPathConstants.NODESET);
for (int i = 0; i < list.getLength(); i++) {
Node node = list.item(i);
System.out.println(node.getNodeName());
}

evaluate() 方法被声明为返回 Object。实际返回什么依赖于 XPath 表达式的结果以及要求的类型。一般来说,XPath 的
number 映射为 java.lang.Double
string 映射为 java.lang.String
boolean 映射为 java.lang.Boolean
node-set 映射为 org.w3c.dom.NodeList

在 Java 中计算 XPath 表达式时,第二个参数指定需要的返回类型。有五种可能,都在 javax.xml.xpath.XPathConstants 类中命名了常量:
XPathConstants.NODESET
XPathConstants.BOOLEAN
XPathConstants.NUMBER
XPathConstants.STRING
XPathConstants.NODE

在使用xpath解析xml的时候还有很多需要注意的地方,若 XML 文档中的元素在名称空间中,查询该文档的 XPath 表达式必须使用相同的名称空间。XPath 表达式不一定要使用相同的前缀,只需要名称空间 URI 相同即可。事实上,如果 XML 文档使用默认名称空间,那么尽管目标文档没有使用前缀,XPath 表达式也必须使用前缀。另外我们也还可以在java中扩展xpath的函数。更多信息请参看下面的参考资料。

参考资料:
[url=http://www.ibm.com/developerworks/cn/xml/x-javaxpathapi.html]Java 语言的 XPath API[/url]
[url=http://www.ibm.com/developerworks/library/x-wxxm35.html?S_TACT=105AGX52&S_CMP=cn-a-x]Working XML: Get started with XPath 2.0[/url]
[url=http://www.w3school.com.cn/xpath/index.asp]XPath 教程[/url]
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值