1。xml背景
格式良好的(web-fromed)xml可以不需要文檔類型定義(DTD),只要滿足基本的xml格式規(guī)范就可以認(rèn)為是格式良好的xml文檔。但是格式標(biāo)準(zhǔn),只能說明元素、標(biāo)簽、格式是合法的,并不能說明元素是有意義的,或者說規(guī)范的。
有效的xml文檔,首先要求是格式良好的文檔,同時遵守相應(yīng)的DTD文件約束。
2。xml解析
xml文檔解析的大致使用過程如下圖:

由xml解析器解析和操作指定的xml文檔,然后提供接口供應(yīng)用程序使用。如果解析器不同,那么提供的接口就有可能不同。慶幸的是,目前所有的xml解析器對兩套標(biāo)準(zhǔn)的api提供了支持,這兩套標(biāo)準(zhǔn)api就是dom和sax。
dom:即document object model,文檔對象模型,它是w3c組織推薦的處理xml的標(biāo)準(zhǔn)接口。dom是基于xml文檔結(jié)構(gòu)樹的解析。
sax:即simple api for xml,它是非官方的、xml社區(qū)事實上的標(biāo)準(zhǔn)。sax是基于事件流的解析。
dom和sax只是定義了一些接口以及某些接口的缺省實現(xiàn),應(yīng)用程序要想利用dom或sax訪問xml文檔,還需要真正實現(xiàn)dom或sax接口的xml解析器。apache的xerces是一個使用非常廣泛的解析器,它實現(xiàn)了dom和sax的調(diào)用接口,并提供了多種語言的實現(xiàn)版本。
3。java語言對xml文檔的解析
首先介紹jaxp:
基于dom或sax提供的api接口,使用相應(yīng)的解析器實現(xiàn)類我們已經(jīng)可以對xml進行解析處理了。如下所示:
org.xml.sax.XMLReader sp=new org.apache.xerces.parser.SAXParser();
FileInputStream fis=new FileInputStream(“hello.xml”);
InputSource is=new InputSource(fis);
sp.setContentHandler(new MyConentHandler());
sp.parse(is);
為了屏蔽xml解析器的變化對代碼的影響,java提供了一套標(biāo)準(zhǔn)的處理xml文件的接口(實際上是一些抽象的工廠類),使得java開發(fā)人員以一種標(biāo)準(zhǔn)的方式對xml進行編程,即jaxp(java api for xml processing)。jaxp沒有提供解析xml的新方法,只是在解析器之上封裝一個抽象層。在jdk1.6的文檔中,我們可以看到j(luò)avax.xml,org.w3c.dom,org.xml.sax包及其子包都屬于jaxp的部分。jaxp由接口、抽象類和一些輔助類組成,符合jaxp規(guī)范的解析器實現(xiàn)其中的接口和抽象類,開發(fā)時只需要使用jaxp的api編程,底層的解析器對開發(fā)者時透明的,可以隨意的切換。
那么jaxp出現(xiàn)后,java應(yīng)用程序處理xml文檔的過程就如下圖:

那實際采用哪種解析器的jaxp實現(xiàn),可以通過系統(tǒng)屬性、properties文件等方式來配置。
下面具體介紹幾種java解析xml的方法:
3.1 DOM方式(jaxp)
在javax.xml.parsers包中,定義了dom的抽象工廠類DocumentBuilderFactory,在這個類中有一個靜態(tài)的方法newInstance(),通過它產(chǎn)生一個DocumentBuilderFactory的實例。前面提到過jaxp編程,解析器提供商必須繼承該抽象類產(chǎn)生一個具體的解析器工廠,然后由這個工廠類實例出一個解析器對象,再通過該解析器對象處理xml文檔。那么這個newInstance方法就是用來產(chǎn)生一個具體的解析器工廠類實例,查找生成解析器工廠類實例的方式可參考jdk文檔。
在獲取到解析器工廠類實例類之后,就可以調(diào)用newDocumentBuilder()方法創(chuàng)建一個dom解析器實例;dom解析器實例就可以調(diào)用parser()方法獲取整個xml問答的Document對象。
3 .2 SAX方式(jaxp)
sax是基于事件驅(qū)動的api,sax解析xml文檔時會向事件處理器發(fā)送不同的事件。sax解析器接口和事件處理器接口都在org.xml.sax包中定義。XMLReader即為sax定義的解析器接口,由解析器提供商實現(xiàn)該借口,應(yīng)用程序需要做的是編寫一個事件處理器。可以通過XMLReader的setContentHandler()方法來設(shè)置一個事件處理器的實例。
與dom類似,jaxp也為sax解析器提供了抽象工廠類SAXParserFactory類,sax解析器工廠類的實例與dom解析器工廠類的實例類似,都是通過newInstance()方法來創(chuàng)建,不同的是SAXParserFactory的newInstance()方法查找的工廠類屬性是:javax.xml.parsers.SAXParserFactory。同樣,獲取sax解析器實例的方法,可以通過調(diào)用newSAXParser()。
使用SAXParser和XMLReader都可以用來對xml文檔進行解析,前者只是對后者又一次的包裝。
3.3 JDOM
dom被設(shè)計用于完成幾乎所有的xml操作任務(wù),同時又是與語言無關(guān)的,這就導(dǎo)致dom的api龐大而且復(fù)雜。為了使java程序員更方便地處理xml文檔,兩位國外的java技術(shù)專家創(chuàng)建了jdom。用developerworks上的一句話,“延續(xù)開源社群有需要就創(chuàng)建工具的歷史傳統(tǒng),Java 技術(shù)專家 Jason Hunter 和 Brett McLaughlin 締造了 JDOM”。所以可以認(rèn)為,jdom是一種專門用于java語言解析xml文檔的開放源代碼框架。
jdom也使用對象樹來表示xml文檔,底層使用sax解析器分析xml文檔,形成jdom樹。
3.4 DOM4J
同jdom一樣,dom4j也是應(yīng)用于java平臺,提供簡單、靈活的處理xml文檔的開發(fā)源代碼庫。很有意思的是,dom4j是由早期開發(fā)jdom的人分離出來而后獨立開發(fā)的,(利益或意見不和?呵呵)與jdom相比,dom4j提供了更好的靈活性。從網(wǎng)上的評論可以看出,dom4j從性能、功能、易用性上都優(yōu)于jdom,可以作為解析xml文件的首選。(看來后來分離出的那撥人選擇還是正確的!)流行的hibernate,jaxm都采用了dom4j處理xml文件。
dom4j也使用sax解析器來分析xml文檔,形成dom4j樹;它也提供了用于大文檔的基于事件的處理模型。
所以可以看出,jdom和dom4j只是開源社區(qū)產(chǎn)生出來的方便地解析xml的框架或工具,并沒有創(chuàng)造新的xml解析方式。如果拿
拿以上四種解析xml的方法比較,用孫鑫老師的話,如果你需要頻繁更換解析器就是jaxp方式,否則推薦使用dom4j。