JAVA通过XPath解析XML性能比较
转自【http://www.cnblogs.com/mouse-coder/p/3451243.html】
最近在做一个小项目,使用到XML文件解析技术,通过对该技术的了解和使用,总结了以下内容。
1 XML文件解析的4种方法
通常解析XML文件有四种经典的方法。基本的解析方式有两种,一种叫SAX,另一种叫DOM。SAX是基于事件流的解析,DOM是基于XML文档树结构的解析。在此基础上,为了减少DOM、SAX的编码量,出现了JDOM,其优点是,20-80原则(帕累托法则),极大减少了代码量。通常情况下JDOM使用时满足要实现的功能简单,如解析、创建等要求。但在底层,JDOM还是使用SAX(最常用)、DOM、Xanan文档。另外一种是DOM4J,是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用的特点,同时它也是一个开放源代码的软件。如今你可以看到越来越多的 Java 软件都在使用 DOM4J 来读写 XML,特别值得一提的是连 Sun 的 JAXM 也在用 DOM4J。具体四种方法的使用,百度一下,会有众多详细的介绍。可以参考SMCwwh对以上技术的详细介绍,http://blog.csdn.net/smcwwh/article/details/7183869#part3。
2 XPath简单介绍
XPath 是一门在 XML 文档中查找信息的语言。XPath 用于在 XML 文档中通过元素和属性进行导航,并对元素和属性进行遍历。XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 同时被构建于 XPath 表达之上。因此,对 XPath 的理解是很多高级 XML 应用的基础。XPath非常类似对数据库操作的SQL语言,或者说JQuery,它可以方便开发者抓起文档中需要的东西。其中DOM4J也支持XPath的使用。XPath的具体使用教程可以参考http://www.w3school.com.cn/xpath/index.asp。
3 DOM4J使用XPath
DOM4J使用XPath解析XML文档是,首先需要在项目中引用两个JAR包:
dom4j-1.6.1.jar:DOM4J软件包,下载地址http://sourceforge.net/projects/dom4j/;
jaxen-xx.xx.jar:通常不添加此包,会引发异常(java.lang.NoClassDefFoundError: org/jaxen/JaxenException),下载地址http://www.jaxen.org/releases.html。
3.1 命名空间(namespace)的干扰
在处理由excel文件或其他格式文件转换的xml文件时,通常会遇到通过XPath解析得不到结果的情况。这种情况通常是由于命名空间的存在导致的。以下述内容的XML文件为例,通过XPath=" // Workbook/ Worksheet / Table / Row[1]/ Cell[1]/Data[1] "进行简单的检索,通常是没有结果出现的。这就是由于命名空间namespace(xmlns="urn:schemas-microsoft-com:office:spreadsheet")导致的。

<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">
<Worksheet ss:Name="Sheet1">
<Table ss:ExpandedColumnCount="81" ss:ExpandedRowCount="687" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="52.5" ss:DefaultRowHeight="15.5625">
<Row ss:AutoFitHeight="0">
<Cell>
<Data ss:Type="String">敲代码的耗子</Data>
</Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell>
<Data ss:Type="String">Sunny</Data>
</Cell>
</Row>
</Table>
</Worksheet>
</Workbook>

3.2 XPath对带有命名空间的xml文件解析
第一种方法(read1()函数):使用XPath语法中自带的local-name() 和 namespace-uri() 指定你要使用的节点名和命名空间。 XPath表达式书写较为麻烦。
第二种方法(read2()函数):设置XPath的命名空间,利用setNamespaceURIs()函数。
第三种方法(read3()函数):设置DocumentFactory()的命名空间 ,使用的函数是setXPathNamespaceURIs()。二和三两种方法的XPath表达式书写相对简单。
第四种方法(read4()函数):方法和第三种一样,但是XPath表达式不同(程序具体体现),主要是为了检验XPath表达式的不同,主要指完整程度,是否会对检索效率产生影响。
(以上四种方法均通过DOM4J结合XPath对XML文件进行解析)
第五种方法(read5()函数):使用DOM结合XPath对XML文件进行解析,主要是为了检验性能差异。
没有什么能够比代码更能说明问题的了!果断上代码!

1 package XPath;
2 import java.io.IOException;
3 import java.io.InputStream;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7
8 import javax.xml.parsers.DocumentBuilder;
9 import javax.xml.parsers.DocumentBuilderFactory;
10 import javax.xml.parsers.ParserConfigurationException;
11 import javax.xml.xpath.XPathConstants;
12 import javax.xml.xpath.XPathExpression;
13 import javax.xml.xpath.XPathExpressionException;
14 import javax.xml.xpath.XPathFactory;
15
16 import org.dom4j.Document;
17 import org.dom4j.DocumentException;
18 import org.dom4j.Element;
19 import org.dom4j.XPath;
20 import org.dom4j.io.SAXReader;
21 import org.w3c.dom.NodeList;
22 import org.xml.sax.SAXException;
23
24 /**
25 * DOM4J DOM XML XPath
26 * @author hao
27 */
28 public class TestDom4jXpath {
29 public static void main(String[] args) {
30 read1();
31 read2();
32 read3();
33 read4();//read3()方法一样,但是XPath表达式不同
34 read5();
35 }
36
37 public static void read1() {
38 /*
39 * use local-name() and namespace-uri() in XPath
40 */
41 try {
42 long startTime=System.currentTimeMillis();
43 SAXReader reader = new SAXReader();
44 InputStream in = TestDom4jXpath.class.getClassLoader().getResourceAsStream("XPath\\XXX.xml");
45 Document doc = reader.read(in);
46 /*String xpath ="//*[local-name()='Workbook' and namespace-uri()='urn:schemas-microsoft-com:office:spreadsheet']"
47 + "/*[local-name()='Worksheet']"
48 + "/*[local-name()='Table']"
49 + "/*[local-name()='Row'][4]"
50 + "/*[local-name()='Cell'][3]"
51 + "/*[local-name()='Data'][1]";*/
52 String xpath ="//*[local-name()='Row'][4]/*[local-name()='Cell'][3]/*[local-name()='Data'][1]";
53 System.err.println("=====use local-name() and namespace-uri() in XPath====");
54 System.err.println("XPath:" + xpath);
55 @SuppressWarnings("unchecked")
56 List<Element> list = doc.selectNodes(xpath);
57 for(Object o:list){
58 Element e = (Element) o;
59 String show=e.getStringValue();
60 System.out.println("show = " + show);
61 long endTime=System.currentTimeMillis();
62 System.out.println("程序运行时间: "+(endTime-startTime)+"ms");
63 }
64 } catch (DocumentException e) {
65 e.printStackTrace();
66 }
67 }
68
69 public static void read2() {
70 /*
71 * set xpath namespace(setNamespaceURIs)
72 */
73 try {
74 long startTime=System.currentTimeMillis();
75 Map map = new HashMap();
76 map.put("Workbook","urn:schemas-microsoft-com:office:spreadsheet");
77 SAXReader reader = new SAXReader();
78 InputStream in = TestDom4jXpath.class.getClassLoader().getResourceAsStream("XPath\\XXX.xml");
79 Document doc = reader.read(in);
80 String xpath ="//Workbook:Row[4]/Workbook:Cell[3]/Workbook:Data[1]";
81 System.err.println("=====use setNamespaceURIs() to set xpath namespace====");
82 System.err.println("XPath:" + xpath);
83 XPath x = doc.createXPath(xpath);
84 x.setNamespaceURIs(map);
85 @SuppressWarnings("unchecked")
86 List<Element> list = x.selectNodes(doc);
87 for(Object o:list){
88 Element e = (Element) o;
89 String show=e.getStringValue();
90 System.out.println("show = " + show);
91 long endTime=System.currentTimeMillis();
92 System.out.println("程序运行时间: "+(endTime-startTime)+"ms");
93 }
94 } catch (DocumentException e) {
95 e.printStackTrace();
96 }
97 }
98
99 public static void read3() {
100 /*
101 * set DocumentFactory() namespace(setXPathNamespaceURIs)
102 */
103 try {
104 long startTime=System.currentTimeMillis();
105 Map map = new HashMap();
106 map.put("Workbook","urn:schemas-microsoft-com:office:spreadsheet");
107 SAXReader reader = new SAXReader();
108 InputStream in = TestDom4jXpath.class.getClassLoader().getResourceAsStream("XPath\\XXX.xml");
109 reader.getDocumentFactory().setXPathNamespaceURIs(map);
110 Document doc = reader.read(in);
111 String xpath ="//Workbook:Row[4]/Workbook:Cell[3]/Workbook:Data[1]";
112 System.err.println("=====use setXPathNamespaceURIs() to set DocumentFactory() namespace====");
113 System.err.println("XPath:" + xpath);
114 @SuppressWarnings("unchecked")
115 List<Element> list = doc.selectNodes(xpath);
116 for(Object o:list){
117 Element e = (Element) o;
118 String show=e.getStringValue();
119 System.out.println("show = " + show);
120 long endTime=System.currentTimeMillis();
121 System.out.println("程序运行时间: "+(endTime-startTime)+"ms");
122 }
123 } catch (DocumentException e) {
124 e.printStackTrace();
125 }
126 }
127
128 public static void read4() {
129 /*
130 * 同read3()方法一样,但是XPath表达式不同
131 */
132 try {
133 long startTime=System.currentTimeMillis();
134 Map map = new HashMap();
135 map.put("Workbook","urn:schemas-microsoft-com:office:spreadsheet");
136 SAXReader reader = new SAXReader();
137 InputStream in = TestDom4jXpath.class.getClassLoader().getResourceAsStream("XPath\\XXX.xml");
138 reader.getDocumentFactory().setXPathNamespaceURIs(map);
139 Document doc = reader.read(in);
140 String xpath ="//Workbook:Worksheet/Workbook:Table/Workbook:Row[4]/Workbook:Cell[3]/Workbook:Data[1]";
141 System.err.println("=====use setXPathNamespaceURIs() to set DocumentFactory() namespace====");
142 System.err.println("XPath:" + xpath);
143 @SuppressWarnings("unchecked")
144 List<Element> list = doc.selectNodes(xpath);
145 for(Object o:list){
146 Element e = (Element) o;
147 String show=e.getStringValue();
148 System.out.println("show = " + show);
149 long endTime=System.currentTimeMillis();
150 System.out.println("程序运行时间: "+(endTime-startTime)+"ms");
151 }
152 } catch (DocumentException e) {
153 e.printStackTrace();
154 }
155 }
156
157 public static void read5() {
158 /*
159 * DOM and XPath
160 */
161 try {
162 long startTime=System.currentTimeMillis();
163 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
164 dbf.setNamespaceAware(false);
165 DocumentBuilder builder = dbf.newDocumentBuilder();
166 InputStream in = TestDom4jXpath.class.getClassLoader().getResourceAsStream("XPath\\XXX.xml");
167 org.w3c.dom.Document doc = builder.parse(in);
168 XPathFactory factory = XPathFactory.newInstance();
169 javax.xml.xpath.XPath x = factory.newXPath();
170 //选取所有class元素的name属性
171 String xpath = "//Workbook/Worksheet/Table/Row[4]/Cell[3]/Data[1]";
172 System.err.println("=====Dom XPath====");
173 System.err.println("XPath:" + xpath);
174 XPathExpression expr = x.compile(xpath);
175 NodeList nodes = (NodeList)expr.evaluate(doc, XPathConstants.NODE);
176 for(int i = 0; i<nodes.getLength();i++) {
177 System.out.println("show = " + nodes.item(i).getNodeValue());
178 long endTime=System.currentTimeMillis();
179 System.out.println("程序运行时间: "+(endTime-startTime)+"ms");
180 }
181 } catch(XPathExpressionException e) {
182 e.printStackTrace();
183 } catch(ParserConfigurationException e) {
184 e.printStackTrace();
185 } catch(SAXException e) {
186 e.printStackTrace();
187 } catch(IOException e) {
188 e.printStackTrace();
189 }
190 }
191 }

3.3 不同方法的性能比较
为了比较几种方法的解析性能,实验过程中使用了6M以上大小,7万行以上的XML文件(XXX.xml)进行10轮测试,如下所述:
图1 XPath使用性能对比
方法名称 |
平均运行时间 |
XPath表达式 |
read1() |
1663ms |
//*[local-name()='Row'][4]/*[local-name()='Cell'][3]/*[local-name()='Data'][1] |
read2() |
2184ms |
//Workbook:Row[4]/Workbook:Cell[3]/Workbook:Data[1] |
read3() |
601ms |
//Workbook:Row[4]/Workbook:Cell[3]/Workbook:Data[1] |
read4() |
472ms |
//Workbook:Worksheet/Workbook:Table/Workbook:Row[4]/Workbook:Cell[3]/Workbook:Data[1] |
read5() |
1094ms |
//Workbook/Worksheet/Table/Row[4]/Cell[3]/Data[1] |
表1 平均性能统计
由以上性能对比可知:
1、read4()方法运行时间最短,即运用DOM4J方法调用全路径(从根节点出发)XPath表达式解析XML文件耗时最短;
2、运用DOM解析方法所使用的XPath表达式最为简单(可以写作//Row[4]/Cell[3]/Data[1]),因DOM中可以通过setNamespaceAware(false)方法使命名空间失效。
JAVA通过XPath解析XML性能比较的更多相关文章
- JAVA通过XPath解析XML性能比较(原创)
(转载请标明原文地址) 最近在做一个小项目,使用到XML文件解析技术,通过对该技术的了解和使用,总结了以下内容. 1 XML文件解析的4种方法 通常解析XML文件有四种经典的方法.基本的解析方式有两种 ...
- java结合XPATH解析XML
做自动化测试的人,都应该对XPATH很熟悉了,但是在用JAVA解析XML时,我们通常是一层层的遍历进去,这样的代码的局限性很大,也不方便,于是我们结合一下XPATH,来解决这个问题. 所需要的JAR包 ...
- Xpath解析xml
Xpath解析xml其实最主要的是查找xml文档中信息,而且不需要了解xml文档结构 package com.huawei.xml; import java.io.InputStream;import ...
- Java用SAX解析XML
要解析的XML文件:myClass.xml <?xml version="1.0" encoding="utf-8"?> <class> ...
- java使用dom4j和XPath解析XML与.net 操作XML小结
最近研究java的dom4j包,使用 dom4j包来操作了xml 文件 包括三个文件:studentInfo.xml(待解析的xml文件), Dom4jReadExmple.java(解析的主要类), ...
- 【java】:解析xml
==========================================xml文件<?xml version="1.0" encoding="GB231 ...
- 简单用DOM4J结合XPATH解析XML
由于DOM4J在解析XML时只能一层一层解析,所以当XML文件层数过多时使用会很不方便,结合XPATH就可以直接获取到某个元素 使用dom4j支持xpath的操作的几种主要形式 第一种形式 ...
- Java中Dom4j解析XML
与利用DOM.SAX.JAXP机制来解析xml相比DOM4J表现更优秀,具有性能优异.功能强大和极端易用使用的特点,只要懂得DOM基本概念,就可以通过dom4j的api文档来解析xml.dom4j是一 ...
- java三方---->dom4j解析xml数据
Dom4j是一个易用的.开源的库,用于XML,XPath和XSLT.它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX和JAXP.今天我们就开始Dom4j的学习. Dom4j的使用 ...
随机推荐
- C# 实现简单仿QQ登陆注册功能
闲来没事,想做一个仿QQ登陆注册的winform,于是利用工作之余,根据自己的掌握和查阅的资料,历时4天修改完成,新手水平,希望和大家共同学习进步,有不同见解希望提出! 废话不多说,进入正题: 先来看 ...
- 定时任务 Wpf.Quartz.Demo.2
定时任务 Wpf.Quartz.Demo.1已经能运行了,本节开始用wpf搭界面. 准备工作: 1.界面选择MahApp.Metro 在App.xaml添加资源 <Application.Res ...
- windform 重绘Treeview "+-"号图标
模仿wind系统界面,重绘Treeview + - 号图标 一,首先需要图片 ,用于替换原有的 +-号 二.新建Tree扩展类 TreeViewEx继承TreeView using System; u ...
- 【BZOJ3551】 [ONTAK2010]Peaks加强版
BZOJ3551 [ONTAK2010]Peaks加强版 Solution Kruscal重构树后发现可以对于小于的离散化然后倍增+主席树找到上一个的可行解. 然后就可以了. 如果数组开的不好,容易在 ...
- JavaScript基础(2)-DOM
一.伪数组arguments arguments代表的是实参,有个讲究的地方是:arguments只在函数中使用. 1.返回函数实参的个数:arguments.length,例如: fn(2,4); ...
- 解决 canvas 绘图在高清屏中的模糊问题
解决 canvas 绘图在高清屏中的模糊问题 为什么模糊 CSS 像素是一个抽象单位(1 px),浏览器根据某种规则将 css 像素转化为屏幕需要的实际像素值. 在高清屏之前,屏幕上显示一个像素点需要 ...
- Html 常见meta
html 的meta标签对网页渲染及SEO搜索引擎起着不可忽视的作用.详细的写法一段时间不写,容易忘,所以整理了一下,方便需要时查看. <!DOCTYPE html> <!-- 使用 ...
- Java - Tips
001 - Java中print.printf与println的区别? printf:格式化输出,用来控制输出的格式. print:标准输出,不换行. println:标准输出,换行.例如,print ...
- String.format(String format,Object... args)的用法
String.format(String format, Object... args)方法详解 以前也看到过很多次这个用法,一直记不牢靠,今天整理一下. 我仅仅举几个例子稍做说明: String ...
- POJ 2453
#include <iostream> #include <algorithm> #include <cmath> #define MAXN 1000 #defin ...