`
ajax_xu
  • 浏览: 151606 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

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的基本语法,后面再举详细的例子。节点选取语法:

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


谓词(用来查找某个特定的节点或者包含某个指定的值的节点,通常使用在[]内)
路径表达式 结果
/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。


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


路径组合表达式,组合多个路径表达式,扩大选择范围;例如:
//book/title | //book/price 选取所有 book 元素的 title 和 price 元素。

另外,关于xpath的轴和运算符这里就不再细说了,有兴趣的可以参看后面的参看资料。
下面给出一个实例,展示如何在java中使用xpath提取xml中的信息
xml文件test.xml的内容:
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代码:
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文件
Java代码 
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:
Java代码 
XPathFactory factory = XPathFactory.newInstance(); 

3、然后使用这个工厂创建 XPath 对象:
Java代码 
XPath xPath = factory.newXPath(); 

4、使用XPath 对象编译 XPath 表达式:
Java代码 
XPathExpression expression = xPath.compile("//book/title[@lang=\"en\"]"); 

5、使用表达式的evaluate(),并处理结果:
Java代码 
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的函数。更多信息请参看下面的参考资料。
转载  http://berdy.iteye.com/blog/807883
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics