淺析SAX,DOM,JAXP,JDOM與DOM4J之間的關(guān)系

java xml api

眾所周知窜管,SAXDOM是JAVA中兩大核心XML解析API類庫揩尸,而JAXP,JDOMDOM4J都是基于這兩大核心API而衍生出來的宛渐。今日興起看了看相關(guān)資料,寫篇文章總結(jié)總結(jié).仿耽。

SAX與DOM

首先需要說明白的是SAX與DOM的關(guān)系合冀。

SAXDOM都是底層API,在JDK中他們的包路徑分別為:org.xml.sax與org.w3c.dom项贺。自JDK1.5開始君躺,JDK中自帶的實(shí)現(xiàn)為Apache的xerces(位于com.sun.org.apache.xerces.internal.parsers下)。

SAXSimple API for XML的簡稱开缎,它是在JAVA平臺上第一個(gè)被廣泛使用的XML API棕叫。也就說它是為JAVA而出現(xiàn)的。目前已經(jīng)有多個(gè)語言版本奕删,比如C++俺泣。
DOMDocuments Object Model的簡稱,與SAX不同的是完残,DOM是W3C的標(biāo)準(zhǔn)伏钠,它出現(xiàn)的目的是為了實(shí)現(xiàn)一套跨平臺與語言的標(biāo)準(zhǔn)。

以上是它們之間的第一個(gè)不同谨设。第二個(gè)熟掂,就是解析方式的不同。

SAX是基于事件解析铝宵,解析過程中根據(jù)目前的XML元素類型打掘,調(diào)用用戶自己實(shí)現(xiàn)的回調(diào)方法(或著叫事件方法)來處理华畏,如:startDocument();鹏秋,startElement(); 尊蚁。
SAX2.0中有4個(gè)核心接口:

  • org.xml.sax.ContentHander
  • org.xml.sax.ErrorHandler
  • org.xml.sax.DTDHandler
  • org.xml.sax.EntityResolver

實(shí)現(xiàn)這幾個(gè)Handler,然后調(diào)用解析器相應(yīng)的set方法注冊給解析器侣夷,就可以完成各種元素的解析與處理横朋。 對應(yīng)的注冊進(jìn)解析器的方法分別是:

  • parser.setContentHandler(ContentHander handler)
  • parser.setErrorHandler(ErrorHandler handler)
  • parser.setDTDHandler(DTDHandler handler)
    完整例子:
 DefaultHandler  handler=new XmlParserHandler();//DefaultHandler已經(jīng)實(shí)現(xiàn)了全部org.xml.sax.ContentHandler,  
                                                   //org.xml.sax.ErrortHandler百拓,org.xml.sax.DTDHandler和org.xml.sax.EntityHandler接口  
 XMLReader xr=XMLReaderFactory.createXMLReader();//獲取解析器實(shí)例  
 xr.setContentHandler(handler);//設(shè)置處理類  
        xr.setErrorHandler(handler);  
        xr.setDTDHandler(handler);  
xr.setFeature("http://xml.org/sax/features/validation", true);//開啟DTD驗(yàn)證  
xr.setFeature("http://apache.org/xml/features/validation/schema", true);//開啟SCHMAE驗(yàn)證  
xr.parse(new InputSource("F:/Work/Workspace/XmlStudy/test.xml"));  

基于事件處理的好處是琴锭,不需要等到整個(gè)XML文件被加載完成后在開始處理,而是加載到哪處理到哪衙传。這樣便帶來了效率上的優(yōu)勢决帖。但是其也有明顯的不足,第一個(gè)不足便是無法隨機(jī)訪問元素蓖捶。如果你只想獲取第二元素的信息地回,那么你必須等到第一個(gè)元素處理完成后,第二個(gè)元素開始的時(shí)候俊鱼。如果這時(shí)刻像,你又需要返回第一個(gè)元素,那么對不起并闲,已經(jīng)來不及了细睡。SAX不會主動記憶或保存已處理過的元素(為了效率)。為了實(shí)現(xiàn)前面的需求帝火,開發(fā)人員需要自己使用容器來保存處理過的元素溜徙,并且建立一個(gè)模型來表示XML的樹形結(jié)構(gòu)。這樣一來也就帶來了第二個(gè)缺點(diǎn)犀填,使用的復(fù)雜性萌京。

再來說說DOM。DOM采用了解析方式是一次性加載整個(gè)XML文檔宏浩,在內(nèi)存中形成一個(gè)樹形的數(shù)據(jù)結(jié)構(gòu)知残,這個(gè)數(shù)據(jù)結(jié)構(gòu)我們稱為文檔對象模型。通過DOM解析器獲取Documen文檔t對象后比庄,開發(fā)人員可以很方便的對其進(jìn)行操作求妹,如getDocumentElement();(獲取更元素)getFirstChild();獲取一個(gè)子元素佳窑,appendChild();增加子元素制恍,removeChild();移除子元素。因此神凑,使用DOM可以很方便對XML中的數(shù)據(jù)進(jìn)行獲取與修改净神,而不需要像SAX一樣自己設(shè)計(jì)模型保存獲取的數(shù)據(jù)何吝。
完整例子:

  DOMParser dp=new DOMParser();  
  dp.parse(new InputSource("e:/test.xml"));  
  Document doc=dp.getDocument();  
  Element rootElemet=doc.getDocumentElement();  
  NodeList list=rootElemet.getChildNodes();  

跟重要的一點(diǎn)是,在DOM中所有Element都是Node鹃唯,這意味著爱榕,我們不需要明確知道文檔的結(jié)構(gòu)就可以操作它。我們可以判斷當(dāng)前獲取到的任意Node對象類型來做不同操作坡慌。主要Node類型有:
- Node.DOCUMENT_NODE
- Node.ELEMENT_NODE
- Node.TEXT_NODE
- Node.CDATA_SECTION_NODE
- Node.PROCESSING_INSTRUCTION_NODE
- Node.ENTITY_REFERENCE_NODE
- Node.DOCUMENT_TYPE_NODE

但是黔酥,由于DOM是一次性加載整個(gè)XML文件到內(nèi)存, 如果XML文件非常龐大洪橘,構(gòu)建文檔樹的內(nèi)存與時(shí)間開銷會很大跪者,且很有可能導(dǎo)致內(nèi)存溢出異常。

那么如何在SAX與DOM直接選擇呢熄求?這取決于下面幾個(gè)因素:

  1. 應(yīng)用程序的目的:如果打算對數(shù)據(jù)作出更改并將它輸出為 XML渣玲,那么在大多數(shù)情況下,DOM 是適當(dāng)?shù)倪x擇弟晚。并不是說使用 SAX 就不能更改數(shù)據(jù)忘衍,但是該過程要復(fù)雜得多,因?yàn)槟仨殞?shù)據(jù)的一份拷貝而不是對數(shù)據(jù)本身作出更改指巡。
  2. 數(shù)據(jù)容量: 對于大型文件淑履,SAX 是更好的選擇。
  3. 數(shù)據(jù)將如何使用:如果只有數(shù)據(jù)中的少量部分會被使用藻雪,那么使用 SAX 來將該部分?jǐn)?shù)據(jù)提取到應(yīng)用程序中可能更好秘噪。 另一方面,如果您知道自己以后會回頭引用已處理過的大量信息勉耀,那么 SAX 也許不是恰當(dāng)?shù)倪x擇指煎。
  4. 對速度的需要: SAX 實(shí)現(xiàn)通常要比 DOM 實(shí)現(xiàn)更快。

SAXDOM 不是相互排斥的便斥,記住這點(diǎn)很重要至壤。您可以使用 DOM 來創(chuàng)建 SAX 事件流,也可以使用 SAX 來創(chuàng)建 DOM 樹枢纠。事實(shí)上像街,用于創(chuàng)建 DOM 樹的大多數(shù)解析器實(shí)際上都使用 SAX 來完成這個(gè)任務(wù),比如DOM4JJDOM晋渺!

JAXP,JDOM與DOM4J

JAXP

JAXP镰绎,全稱Java API for XML Processing,打開其為JDK的目錄:javax.xml.parsers木西, 你會發(fā)現(xiàn)它與SAX和DOM一樣只是一套API畴栖。實(shí)際上,JAXP出現(xiàn)時(shí)SUN公司為了彌補(bǔ)JAVA在XML標(biāo)準(zhǔn)制定上的空白而制定的一套JAVA XML標(biāo)準(zhǔn)API八千。它并沒有為JAVA解析XML提供任何新功能吗讶,但是它為在JAVA獲取SAX與DOM解析器提供了更加直接的途徑燎猛。它封裝了SAX與DOM兩種接口,并在SAX與DOM的基礎(chǔ)之上照皆,作了一套比較簡單的api以供開發(fā)重绷。
例如:JAXP獲取SAX解析器:

  SAXParserFactory factory=SAXParserFactory.newInstance();  
  SAXParser parser=factory.newSAXParser();  
  parser.parse("F:/Work/Workspace/xiongqi/XmlStudy/test.xml", handler);  

獲取DOM解析器:

  DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();  
  DocumentBuilder builder= factory.newDocumentBuilder();  
  Document document= builder.parse("F:/Work/Workspace/xiongqi/XmlStudy/test.xml");  

在 JAXP 的早期版本中,自帶解析器的實(shí)現(xiàn)為 Apachede 的Crimson纵寝,在 JAXP 的新版本中 (包括在 JDK 中) 论寨,Sun 已經(jīng)重新包裝了 Apache Xerces 做為解析器的實(shí)現(xiàn)星立。

JDOM

由于DOM是為了實(shí)現(xiàn)一套跨平臺與語言的標(biāo)準(zhǔn)爽茴,因此使用它對于JAVA開發(fā)人員來說并不是特別的得心應(yīng)手,這時(shí)JDOM就出現(xiàn)了绰垂。

JDOM 的目的是成為 Java 特定文檔模型室奏,它簡化與 XML 的交互并且比使用 DOM 實(shí)現(xiàn)更快。而且它是第一個(gè) Java 特定模型劲装。與DOM相比較胧沫,首先,JDOM 僅使用具體類而不使用接口占业。這在某些方面簡化了API绒怨,但是也限制了靈活性。第二谦疾,API 大量使用了 Collections 類南蹂,相對于dom中的Node,簡化了那些已經(jīng)熟悉這些類的Java 開發(fā)者的使用念恍。JDOM 自身不包含解析器六剥,默認(rèn)使用隨jar包一起發(fā)行的pache Xerces。

例子:

SAXBuilder builder = new SAXBuilder(false);  
Document doc = builder.build(in);  

從上面代碼中可以看出峰伙,JDOM使用SAX2 解析器來解析和驗(yàn)證輸入 XML 文檔疗疟,然后構(gòu)建Doucment對象。

DOM4J

DOM4J 最初是 JDOM 的一個(gè)分支瞳氓。它合并了許多超出基本 XML 文檔表示的功能策彤,包括集成的 XPath 支持、XML Schema 支持以及用于大文檔或流化文檔的基于事件的處理匣摘。它還提供了構(gòu)建文檔表示的選項(xiàng)店诗,它通過 DOM4J API 和標(biāo)準(zhǔn) DOM 接口具有并行訪問功能。

為支持所有這些功能恋沃,DOM4J 使用接口抽象基本類方法必搞。DOM4J 大量使用了 API 中的Collections 類,但是在許多情況下囊咏,它還提供一些替代方法以允許更好的性能或更直接的編碼方法恕洲。直接好處是塔橡,雖然 DOM4J 付出了更復(fù)雜的 API 的代價(jià),但是它提供了比 JDOM 大得多的靈活性霜第。在添加靈活性葛家、XPath 集成和對大文檔處理的目標(biāo)時(shí),DOM4J 的目標(biāo)與 JDOM 是一樣的:針對 Java開發(fā)者的易用性和直觀操作泌类。它還致力于成為比 JDOM 更完整的解決方案癞谒,實(shí)現(xiàn)在本質(zhì)上處理所有Java/XML 問題的目標(biāo)。在完成該目標(biāo)時(shí)刃榨,它比 JDOM 更少強(qiáng)調(diào)防止不正確的應(yīng)用程序行為弹砚。

例子:

SAXReader reader = new SAXReader(false);  
Document  doc = reader.read(in);  

DOM4J 是一個(gè)非常非常優(yōu)秀的Java XML API,具有性能優(yōu)異枢希、功能強(qiáng)大和極端易用使用的特點(diǎn)桌吃,同時(shí)它也是一個(gè)開放源代碼的軟件。如今你可以看到越來越多的 Java 軟件都在使用 DOM4J 來讀寫 XML苞轿,特別值得一提的是連 Sun 的 JAXM 也在用 DOM4J茅诱。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市搬卒,隨后出現(xiàn)的幾起案子瑟俭,更是在濱河造成了極大的恐慌,老刑警劉巖契邀,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件摆寄,死亡現(xiàn)場離奇詭異,居然都是意外死亡蹂安,警方通過查閱死者的電腦和手機(jī)椭迎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來田盈,“玉大人畜号,你說我怎么就攤上這事≡是疲” “怎么了简软?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長述暂。 經(jīng)常有香客問我痹升,道長,這世上最難降的妖魔是什么畦韭? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任疼蛾,我火速辦了婚禮,結(jié)果婚禮上艺配,老公的妹妹穿的比我還像新娘察郁。我一直安慰自己衍慎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布皮钠。 她就那樣靜靜地躺著稳捆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪麦轰。 梳的紋絲不亂的頭發(fā)上乔夯,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機(jī)與錄音款侵,去河邊找鬼末荐。 笑死,一個(gè)胖子當(dāng)著我的面吹牛喳坠,可吹牛的內(nèi)容都是我干的鞠评。 我是一名探鬼主播茂蚓,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼壕鹉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了聋涨?” 一聲冷哼從身側(cè)響起晾浴,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎牍白,沒想到半個(gè)月后脊凰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡茂腥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年狸涌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片最岗。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡帕胆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出般渡,到底是詐尸還是另有隱情懒豹,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布驯用,位于F島的核電站脸秽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蝴乔。R本人自食惡果不足惜记餐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望薇正。 院中可真熱鬧片酝,春花似錦巩剖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至晦炊,卻和暖如春鞠鲜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背断国。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工贤姆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人稳衬。 一個(gè)月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓霞捡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親薄疚。 傳聞我的和親對象是個(gè)殘疾皇子蔑滓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容