一般解析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。html
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。java
DOM4J使用XPath解析XML文檔是,首先須要在項目中引用兩個JAR包:node
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。dom
在處理由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>
第一種方法(read1()函數):使用XPath語法中自帶的local-name() 和 namespace-uri() 指定你要使用的節點名和命名空間。 XPath表達式書寫較爲麻煩。性能
第二種方法(read2()函數):設置XPath的命名空間,利用setNamespaceURIs()函數。測試
第三種方法(read3()函數):設置DocumentFactory()的命名空間 ,使用的函數是setXPathNamespaceURIs()。二和三兩種方法的XPath表達式書寫相對簡單。ui
第四種方法(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 }
爲了比較幾種方法的解析性能,實驗過程當中使用了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 平均性能統計
由以上性能對比可知:
一、read4()方法運行時間最短,即運用DOM4J方法調用全路徑(從根節點出發)XPath表達式解析XML文件耗時最短;
二、運用DOM解析方法所使用的XPath表達式最爲簡單(能夠寫做//Row[4]/Cell[3]/Data[1]),因DOM中能夠經過setNamespaceAware(false)方法使命名空間失效。