您好,登錄后才能下訂單哦!
最近在做一個(gè)小項(xiàng)目,使用到XML文件解析技術(shù),通過對該技術(shù)的了解和使用,總結(jié)了以下內(nèi)容。
1 XML文件解析的4種方法
通常解析XML文件有四種經(jīng)典的方法?;镜慕馕龇绞接袃煞N,一種叫SAX,另一種叫DOM。SAX是基于事件流的解析,DOM是基于XML文檔樹結(jié)構(gòu)的解析。在此基礎(chǔ)上,為了減少DOM、SAX的編碼量,出現(xiàn)了JDOM,其優(yōu)點(diǎn)是,20-80原則(帕累托法則),極大減少了代碼量。通常情況下JDOM使用時(shí)滿足要實(shí)現(xiàn)的功能簡單,如解析、創(chuàng)建等要求。但在底層,JDOM還是使用SAX(最常用)、DOM、Xanan文檔。另外一種是DOM4J,是一個(gè)非常非常優(yōu)秀的Java XML API,具有性能優(yōu)異、功能強(qiáng)大和極端易用的特點(diǎn),同時(shí)它也是一個(gè)開放源代碼的軟件。如今你可以看到越來越多的 Java 軟件都在使用 DOM4J 來讀寫 XML,特別值得一提的是連 Sun 的 JAXM 也在用 DOM4J。
2 XPath簡單介紹
XPath 是一門在 XML 文檔中查找信息的語言。XPath 用于在 XML 文檔中通過元素和屬性進(jìn)行導(dǎo)航,并對元素和屬性進(jìn)行遍歷。XPath 是 W3C XSLT 標(biāo)準(zhǔn)的主要元素,并且 XQuery 和 XPointer 同時(shí)被構(gòu)建于 XPath 表達(dá)之上。因此,對 XPath 的理解是很多高級 XML 應(yīng)用的基礎(chǔ)。XPath非常類似對數(shù)據(jù)庫操作的SQL語言,或者說JQuery,它可以方便開發(fā)者抓起文檔中需要的東西。其中DOM4J也支持XPath的使用。
3 DOM4J使用XPath
DOM4J使用XPath解析XML文檔是,首先需要在項(xiàng)目中引用兩個(gè)JAR包:
dom4j-1.6.1.jar:DOM4J軟件包,下載地址http://sourceforge.net/projects/dom4j/;
jaxen-xx.xx.jar:通常不添加此包,會(huì)引發(fā)異常(java.lang.NoClassDefFoundError: org/jaxen/JaxenException),下載地址http://www.jaxen.org/releases.html。
3.1 命名空間(namespace)的干擾
在處理由excel文件或其他格式文件轉(zhuǎn)換的xml文件時(shí),通常會(huì)遇到通過XPath解析得不到結(jié)果的情況。這種情況通常是由于命名空間的存在導(dǎo)致的。以下述內(nèi)容的XML文件為例,通過XPath=" // Workbook/ Worksheet / Table / Row[1]/ Cell[1]/Data[1] "進(jìn)行簡單的檢索,通常是沒有結(jié)果出現(xiàn)的。這就是由于命名空間namespace(xmlns="urn:schemas-microsoft-com:office:spreadsheet")導(dǎo)致的。
<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()函數(shù)):使用XPath語法中自帶的local-name() 和 namespace-uri() 指定你要使用的節(jié)點(diǎn)名和命名空間。 XPath表達(dá)式書寫較為麻煩。
第二種方法(read2()函數(shù)):設(shè)置XPath的命名空間,利用setNamespaceURIs()函數(shù)。
第三種方法(read3()函數(shù)):設(shè)置DocumentFactory()的命名空間 ,使用的函數(shù)是setXPathNamespaceURIs()。二和三兩種方法的XPath表達(dá)式書寫相對簡單。
第四種方法(read4()函數(shù)):方法和第三種一樣,但是XPath表達(dá)式不同(程序具體體現(xiàn)),主要是為了檢驗(yàn)XPath表達(dá)式的不同,主要指完整程度,是否會(huì)對檢索效率產(chǎn)生影響。(以上四種方法均通過DOM4J結(jié)合XPath對XML文件進(jìn)行解析)
第五種方法(read5()函數(shù)):使用DOM結(jié)合XPath對XML文件進(jìn)行解析,主要是為了檢驗(yàn)性能差異。
沒有什么能夠比代碼更能說明問題的了!果斷上代碼!
package XPath; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.XPath; import org.dom4j.io.SAXReader; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** * DOM4J DOM XML XPath * @author hao */ public class TestDom4jXpath { public static void main(String[] args) { read1(); read2(); read3(); read4();//read3()方法一樣,但是XPath表達(dá)式不同 read5(); } public static void read1() { /* * use local-name() and namespace-uri() in XPath */ try { long startTime=System.currentTimeMillis(); SAXReader reader = new SAXReader(); InputStream in = TestDom4jXpath.class.getClassLoader().getResourceAsStream("XPath\\XXX.xml"); Document doc = reader.read(in); /*String xpath ="http://*[local-name()='Workbook' and namespace-uri()='urn:schemas-microsoft-com:office:spreadsheet']" + "/*[local-name()='Worksheet']" + "/*[local-name()='Table']" + "/*[local-name()='Row'][4]" + "/*[local-name()='Cell'][3]" + "/*[local-name()='Data'][1]";*/ String xpath ="http://*[local-name()='Row'][4]/*[local-name()='Cell'][3]/*[local-name()='Data'][1]"; System.err.println("=====use local-name() and namespace-uri() in XPath===="); System.err.println("XPath:" + xpath); @SuppressWarnings("unchecked") List<Element> list = doc.selectNodes(xpath); for(Object o:list){ Element e = (Element) o; String show=e.getStringValue(); System.out.println("show = " + show); long endTime=System.currentTimeMillis(); System.out.println("程序運(yùn)行時(shí)間: "+(endTime-startTime)+"ms"); } } catch (DocumentException e) { e.printStackTrace(); } } public static void read2() { /* * set xpath namespace(setNamespaceURIs) */ try { long startTime=System.currentTimeMillis(); Map map = new HashMap(); map.put("Workbook","urn:schemas-microsoft-com:office:spreadsheet"); SAXReader reader = new SAXReader(); InputStream in = TestDom4jXpath.class.getClassLoader().getResourceAsStream("XPath\\XXX.xml"); Document doc = reader.read(in); String xpath ="http://Workbook:Row[4]/Workbook:Cell[3]/Workbook:Data[1]"; System.err.println("=====use setNamespaceURIs() to set xpath namespace===="); System.err.println("XPath:" + xpath); XPath x = doc.createXPath(xpath); x.setNamespaceURIs(map); @SuppressWarnings("unchecked") List<Element> list = x.selectNodes(doc); for(Object o:list){ Element e = (Element) o; String show=e.getStringValue(); System.out.println("show = " + show); long endTime=System.currentTimeMillis(); System.out.println("程序運(yùn)行時(shí)間: "+(endTime-startTime)+"ms"); } } catch (DocumentException e) { e.printStackTrace(); } } public static void read3() { /* * set DocumentFactory() namespace(setXPathNamespaceURIs) */ try { long startTime=System.currentTimeMillis(); Map map = new HashMap(); map.put("Workbook","urn:schemas-microsoft-com:office:spreadsheet"); SAXReader reader = new SAXReader(); InputStream in = TestDom4jXpath.class.getClassLoader().getResourceAsStream("XPath\\XXX.xml"); reader.getDocumentFactory().setXPathNamespaceURIs(map); Document doc = reader.read(in); String xpath ="http://Workbook:Row[4]/Workbook:Cell[3]/Workbook:Data[1]"; System.err.println("=====use setXPathNamespaceURIs() to set DocumentFactory() namespace===="); System.err.println("XPath:" + xpath); @SuppressWarnings("unchecked") List<Element> list = doc.selectNodes(xpath); for(Object o:list){ Element e = (Element) o; String show=e.getStringValue(); System.out.println("show = " + show); long endTime=System.currentTimeMillis(); System.out.println("程序運(yùn)行時(shí)間: "+(endTime-startTime)+"ms"); } } catch (DocumentException e) { e.printStackTrace(); } } public static void read4() { /* * 同read3()方法一樣,但是XPath表達(dá)式不同 */ try { long startTime=System.currentTimeMillis(); Map map = new HashMap(); map.put("Workbook","urn:schemas-microsoft-com:office:spreadsheet"); SAXReader reader = new SAXReader(); InputStream in = TestDom4jXpath.class.getClassLoader().getResourceAsStream("XPath\\XXX.xml"); reader.getDocumentFactory().setXPathNamespaceURIs(map); Document doc = reader.read(in); String xpath ="http://Workbook:Worksheet/Workbook:Table/Workbook:Row[4]/Workbook:Cell[3]/Workbook:Data[1]"; System.err.println("=====use setXPathNamespaceURIs() to set DocumentFactory() namespace===="); System.err.println("XPath:" + xpath); @SuppressWarnings("unchecked") List<Element> list = doc.selectNodes(xpath); for(Object o:list){ Element e = (Element) o; String show=e.getStringValue(); System.out.println("show = " + show); long endTime=System.currentTimeMillis(); System.out.println("程序運(yùn)行時(shí)間: "+(endTime-startTime)+"ms"); } } catch (DocumentException e) { e.printStackTrace(); } } public static void read5() { /* * DOM and XPath */ try { long startTime=System.currentTimeMillis(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(false); DocumentBuilder builder = dbf.newDocumentBuilder(); InputStream in = TestDom4jXpath.class.getClassLoader().getResourceAsStream("XPath\\XXX.xml"); org.w3c.dom.Document doc = builder.parse(in); XPathFactory factory = XPathFactory.newInstance(); javax.xml.xpath.XPath x = factory.newXPath(); //選取所有class元素的name屬性 String xpath = "http://Workbook/Worksheet/Table/Row[4]/Cell[3]/Data[1]"; System.err.println("=====Dom XPath===="); System.err.println("XPath:" + xpath); XPathExpression expr = x.compile(xpath); NodeList nodes = (NodeList)expr.evaluate(doc, XPathConstants.NODE); for(int i = 0; i<nodes.getLength();i++) { System.out.println("show = " + nodes.item(i).getNodeValue()); long endTime=System.currentTimeMillis(); System.out.println("程序運(yùn)行時(shí)間: "+(endTime-startTime)+"ms"); } } catch(XPathExpressionException e) { e.printStackTrace(); } catch(ParserConfigurationException e) { e.printStackTrace(); } catch(SAXException e) { e.printStackTrace(); } catch(IOException e) { e.printStackTrace(); } } }
3.3 不同方法的性能比較
為了比較幾種方法的解析性能,實(shí)驗(yàn)過程中使用了6M以上大小,7萬行以上的XML文件(XXX.xml)進(jìn)行10輪測試,如下所述:
圖1 XPath使用性能對比
方法名稱 |
平均運(yùn)行時(shí)間 |
XPath表達(dá)式 |
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 平均性能統(tǒng)計(jì)
由以上性能對比可知:
1、read4()方法運(yùn)行時(shí)間最短,即運(yùn)用DOM4J方法調(diào)用全路徑(從根節(jié)點(diǎn)出發(fā))XPath表達(dá)式解析XML文件耗時(shí)最短;
2、運(yùn)用DOM解析方法所使用的XPath表達(dá)式最為簡單(可以寫作//Row[4]/Cell[3]/Data[1]),因DOM中可以通過setNamespaceAware(false)方法使命名空間失效。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。