預(yù)備
測試環(huán)境:
amd毒龍1.4g oc 1.5g、256m ddr333、windows2000 server sp4、sun jdk 1.4.1+eclipse 2.1+resin 2.1.8,在debug模式下測試。
xml文件格式如下:
?。?xml version="1.0" encoding="gb2312"?><result><value>
?。糿o>a1234</no>
<addr>四川省xx縣xx鎮(zhèn)xx路x段xx號</addr></value><value>
?。糿o>b1234</no>
<addr>四川省xx市xx鄉(xiāng)xx村xx組</addr></value></result>
測試方法:
采用jsp端調(diào)用bean(至于為什么采用jsp來調(diào)用,請參考:http://blog.csdn.net/rosen/archive/2004/10/15/138324.aspx),讓每一種方案分別解析10k、100k、1000k、10000k的xml文件,計算其消耗時間(單位:毫秒)。
jsp文件:
<%@ page contenttype="text/html; charset=gb2312" %><%@ page import="com.test.*"%>
?。糷tml><body><%string args[]={""};myxmlreader.main(args);%></body></html>
測試
首先出場的是dom(jaxp crimson解析器)
dom是用與平臺和語言無關(guān)的方式表示xml文檔的官方w3c標(biāo)準(zhǔn)。dom是以層次結(jié)構(gòu)組織的節(jié)點或信息片斷的集合。這個層次結(jié)構(gòu)允許開發(fā)人員在樹中尋找特定信息。分析該結(jié)構(gòu)通常需要加載整個文檔和構(gòu)造層次結(jié)構(gòu),然后才能做任何工作。由于它是基于信息層次的,因而dom被認(rèn)為是基于樹或基于對象的。dom以及廣義的基于樹的處理具有幾個優(yōu)點。首先,由于樹在內(nèi)存中是持久的,因此可以修改它以便應(yīng)用程序能對數(shù)據(jù)和結(jié)構(gòu)作出更改。它還可以在任何時候在樹中上下導(dǎo)航,而不是像sax那樣是一次性的處理。dom使用起來也要簡單得多。
另一方面,對于特別大的文檔,解析和加載整個文檔可能很慢且很耗資源,因此使用其他手段來處理這樣的數(shù)據(jù)會更好。這些基于事件的模型,比如sax。
bean文件:
package com.test;
import java.io.*;import java.util.*;import org.w3c.dom.*;import javax.xml.parsers.*;
public class myxmlreader{
public static void main(string arge[]){
long lasting =system.currenttimemillis();
try{
file f=new file("data_10k.xml");
documentbuilderfactory factory=documentbuilderfactory.newinstance();
documentbuilder builder=factory.newdocumentbuilder();
document doc = builder.parse(f);
nodelist nl = doc.getelementsbytagname("value");
for (int i=0;i<nl.getlength();i++){
system.out.print("車牌號碼:" + doc.getelementsbytagname("no").item(i).getfirstchild().getnodevalue());
system.out.println("車主地址:" + doc.getelementsbytagname("addr").item(i).getfirstchild().getnodevalue());
}
}catch(exception e){
e.printstacktrace();
}
system.out.println("運行時間:"+(system.currenttimemillis() - lasting)+"毫秒");}}
10k消耗時間:265 203 219 172
100k消耗時間:9172 9016 8891 9000
1000k消耗時間:691719 675407 708375 739656
10000k消耗時間:outofmemoryerror
接著是sax
這種處理的優(yōu)點非常類似于流媒體的優(yōu)點。分析能夠立即開始,而不是等待所有的數(shù)據(jù)被處理。而且,由于應(yīng)用程序只是在讀取數(shù)據(jù)時檢查數(shù)據(jù),因此不需要將數(shù)據(jù)存儲在內(nèi)存中。這對于大型文檔來說是個巨大的優(yōu)點。事實上,應(yīng)用程序甚至不必解析整個文檔;它可以在某個條件得到滿足時停止解析。一般來說,sax還比它的替代者dom快許多。
選擇dom還是選擇sax?
對于需要自己編寫代碼來處理xml文檔的開發(fā)人員來說,
選擇dom還是sax解析模型是一個非常重要的設(shè)計決策。
dom采用建立樹形結(jié)構(gòu)的方式訪問xml文檔,而sax采用的事件模型。
dom解析器把xml文檔轉(zhuǎn)化為一個包含其內(nèi)容的樹,并可以對樹進行遍歷。用dom解析模型的優(yōu)點是編程容易,開發(fā)人員只需要調(diào)用建樹的指令,然后利用navigation apis訪問所需的樹節(jié)點來完成任務(wù)??梢院苋菀椎奶砑雍托薷臉渲械脑?。然而由于使用dom解析器的時候需要處理整個xml文檔,所以對性能和內(nèi)存的要求比較高,尤其是遇到很大的xml文件的時候。由于它的遍歷能力,dom解析器常用于xml文檔需要頻繁的改變的服務(wù)中。
sax解析器采用了基于事件的模型,它在解析xml文檔的時候可以觸發(fā)一系列的事件,當(dāng)發(fā)現(xiàn)給定的tag的時候,它可以激活一個回調(diào)方法,告訴該方法制定的標(biāo)簽已經(jīng)找到。sax對內(nèi)存的要求通常會比較低,因為它讓開發(fā)人員自己來決定所要處理的tag。特別是當(dāng)開發(fā)人員只需要處理文檔中所包含的部分?jǐn)?shù)據(jù)時,sax這種擴展能力得到了更好的體現(xiàn)。但用sax解析器的時候編碼工作會比較困難,而且很難同時訪問同一個文檔中的多處不同數(shù)據(jù)。
bean文件:
package com.test;import org.xml.sax.*;import org.xml.sax.helpers.*;import javax.xml.parsers.*;
public class myxmlreader extends defaulthandler {
java.util.stack tags = new java.util.stack();
public myxmlreader() {
super();}
public static void main(string args[]) {
long lasting = system.currenttimemillis();
try {
saxparserfactory sf = saxparserfactory.newinstance();
saxparser sp = sf.newsaxparser();
myxmlreader reader = new myxmlreader();
sp.parse(new inputsource("data_10k.xml"), reader);
} catch (exception e) {
e.printstacktrace();
}
system.out.println("運行時間:" + (system.currenttimemillis() - lasting) + "毫秒");}
public void characters(char ch[], int start, int length) throws saxexception {
string tag = (string) tags.peek();
if (tag.equals("no")) {
system.out.print("車牌號碼:" + new string(ch, start, length));}if (tag.equals("addr")) {
system.out.println("地址:" + new string(ch, start, length));}}
public void startelement(string uri,string localname,string qname,attributes attrs) {
tags.push(qname);}}
10k消耗時間:110 47 109 78
100k消耗時間:344 406 375 422
1000k消耗時間:3234 3281 3688 3312
10000k消耗時間:32578 34313 31797 31890 30328
然后是jdom http://www.jdom.org/
jdom的目的是成為java特定文檔模型,它簡化與xml的交互并且比使用dom實現(xiàn)更快。由于是第一個java特定模型,jdom一直得到大力推廣和促進。正在考慮通過“java規(guī)范請求jsr-102”將它最終用作“java標(biāo)準(zhǔn)擴展”。從2000年初就已經(jīng)開始了jdom開發(fā)。
jdom與dom主要有兩方面不同。首先,jdom僅使用具體類而不使用接口。這在某些方面簡化了api,但是也限制了靈活性。第二,api大量使用了collections類,簡化了那些已經(jīng)熟悉這些類的java開發(fā)者的使用。
jdom文檔聲明其目的是“使用20%(或更少)的精力解決80%(或更多)java/xml問題”(根據(jù)學(xué)習(xí)曲線假定為20%)。jdom對于大多數(shù)java/xml應(yīng)用程序來說當(dāng)然是有用的,并且大多數(shù)開發(fā)者發(fā)現(xiàn)api比dom容易理解得多。jdom還包括對程序行為的相當(dāng)廣泛檢查以防止用戶做任何在xml中無意義的事。然而,它仍需要您充分理解xml以便做一些超出基本的工作(或者甚至理解某些情況下的錯誤)。這也許是比學(xué)習(xí)dom或jdom接口都更有意義的工作。
jdom自身不包含解析器。它通常使用sax2解析器來解析和驗證輸入xml文檔(盡管它還可以將以前構(gòu)造的dom表示作為輸入)。它包含一些轉(zhuǎn)換器以將jdom表示輸出成sax2事件流、dom模型或xml文本文檔。jdom是在apache許可證變體下發(fā)布的開放源碼。
bean文件:
package com.test;
import java.io.*;import java.util.*;import org.jdom.*;import org.jdom.input.*;
public class myxmlreader {
public static void main(string arge[]) {
long lasting = system.currenttimemillis();
try {
saxbuilder builder = new saxbuilder();
document doc = builder.build(new file("data_10k.xml"));
element foo = doc.getrootelement();
list allchildren = foo.getchildren();
for(int i=0;i<allchildren.size();i++) {
system.out.print("車牌號碼:" + ((element)allchildren.get(i)).getchild("no").gettext());
system.out.println("車主地址:" + ((element)allchildren.get(i)).getchild("addr").gettext());
}
} catch (exception e) {
e.printstacktrace();
}
system.out.println("運行時間:" + (system.currenttimemillis() - lasting) + "毫秒");}}
10k消耗時間:125 62 187 94
100k消耗時間:704 625 640 766
1000k消耗時間:27984 30750 27859 30656
10000k消耗時間:outofmemoryerror
最后是dom4j http://dom4j.sourceforge.net/
雖然dom4j代表了完全獨立的開發(fā)結(jié)果,但最初,它是jdom的一種智能分支。它合并了許多超出基本xml文檔表示的功能,包括集成的xpath支持、xml schema支持以及用于大文檔或流化文檔的基于事件的處理。它還提供了構(gòu)建文檔表示的選項,它通過dom4j api和標(biāo)準(zhǔn)dom接口具有并行訪問功能。從2000下半年開始,它就一直處于開發(fā)之中。
為支持所有這些功能,dom4j使用接口和抽象基本類方法。dom4j大量使用了api中的collections類,但是在許多情況下,它還提供一些替代方法以允許更好的性能或更直接的編碼方法。直接好處是,雖然dom4j付出了更復(fù)雜的api的代價,但是它提供了比jdom大得多的靈活性。
在添加靈活性、xpath集成和對大文檔處理的目標(biāo)時,dom4j的目標(biāo)與jdom是一樣的:針對java開發(fā)者的易用性和直觀操作。它還致力于成為比jdom更完整的解決方案,實現(xiàn)在本質(zhì)上處理所有java/xml問題的目標(biāo)。在完成該目標(biāo)時,它比jdom更少強調(diào)防止不正確的應(yīng)用程序行為。
dom4j是一個非常非常優(yōu)秀的java xml api,具有性能優(yōu)異、功能強大和極端易用使用的特點,同時它也是一個開放源代碼的軟件。如今你可以看到越來越多的java軟件都在使用dom4j來讀寫xml,特別值得一提的是連sun的jaxm也在用dom4j。
bean文件:
package com.test;
import java.io.*;import java.util.*;import org.dom4j.*;import org.dom4j.io.*;
public class myxmlreader {
public static void main(string arge[]) {
long lasting = system.currenttimemillis();
try {
file f = new file("data_10k.xml");
saxreader reader = new saxreader();
document doc = reader.read(f);
element root = doc.getrootelement();
element foo;
for (iterator i = root.elementiterator("value"); i.hasnext();) {
foo = (element) i.next();
system.out.print("車牌號碼:" + foo.elementtext("no"));
system.out.println("車主地址:" + foo.elementtext("addr"));
}
} catch (exception e) {
e.printstacktrace();
}
system.out.println("運行時間:" + (system.currenttimemillis() - lasting) + "毫秒");}}
10k消耗時間:109 78 109 31
100k消耗時間:297 359 172 312
1000k消耗時間:2281 2359 2344 2469
10000k消耗時間:20938 19922 20031 21078
jdom和dom在性能測試時表現(xiàn)不佳,在測試10m文檔時內(nèi)存溢出。在小文檔情況下還值得考慮使用dom和jdom。雖然jdom的開發(fā)者已經(jīng)說明他們期望在正式發(fā)行版前專注性能問題,但是從性能觀點來看,它確實沒有值得推薦之處。另外,dom仍是一個非常好的選擇。dom實現(xiàn)廣泛應(yīng)用于多種編程語言。它還是許多其它與xml相關(guān)的標(biāo)準(zhǔn)的基礎(chǔ),因為它正式獲得w3c推薦(與基于非標(biāo)準(zhǔn)的java模型相對),所以在某些類型的項目中可能也需要它(如在javascript中使用dom)。
sax表現(xiàn)較好,這要依賴于它特定的解析方式。一個sax檢測即將到來的xml流,但并沒有載入到內(nèi)存(當(dāng)然當(dāng)xml流被讀入時,會有部分文檔暫時隱藏在內(nèi)存中)。
無疑,dom4j是這場測試的獲勝者,目前許多開源項目中大量采用dom4j,例如大名鼎鼎的hibernate也用dom4j來讀取xml配置文件。如果不考慮可移植性,那就采用dom4j吧!(文/rosen)
文章整理:站長天空 網(wǎng)址:http://www.z6688.com/
以上信息與文章正文是不可分割的一部分,如果您要轉(zhuǎn)載本文章,請保留以上信息,謝謝!