Dom4j
使用簡(jiǎn)介
作者:冰云
icecloud(AT)sina.com
時(shí)間:
2003.12.15
?
版權(quán)聲明:
本文由冰云完成,首發(fā)于
CSDN
,未經(jīng)許可,不得使用于任何商業(yè)用途。
文中代碼部分引用自
DOM4J
文檔。
歡迎轉(zhuǎn)載,但請(qǐng)保持文章及版權(quán)聲明完整。
如需聯(lián)絡(luò)請(qǐng)發(fā)郵件:
icecloud(AT)sina.com
?
|
??? DOM4J
是
dom4j.org
出品的一個(gè)開(kāi)源
XML
解析包,它的網(wǎng)站中這樣定義:
Dom4j
is an easy to use, open source library for working with XML, XPath and XSLT on the Java platform using the Java Collections Framework and with full support for DOM, SAX and JAXP.
Dom4j
是一個(gè)易用的、開(kāi)源的庫(kù),用于
XML
,
XPath
和
XSLT
。它應(yīng)用于
Java
平臺(tái),采用了
Java
集合框架并完全支持
DOM
,
SAX
和
JAXP
。
DOM4J
使用起來(lái)非常簡(jiǎn)單。只要你了解基本的
XML-DOM
模型,就能使用。然而他自己帶的指南只有短短一頁(yè)(
html
),不過(guò)說(shuō)的到挺全。國(guó)內(nèi)的中文資料很少。因而俺寫(xiě)這個(gè)短小的教程方便大家使用,這篇文章僅談及基本的用法,如需深入的使用,請(qǐng)
……
自己摸索或查找別的資料。
之前看過(guò)
IBM developer
社區(qū)的文章(參見(jiàn)附錄),提到一些
XML
解析包的性能比較,其中
DOM4J
的性能非常出色,在多項(xiàng)測(cè)試中名列前茅。(事實(shí)上
DOM4J
的官方文檔中也引用了這個(gè)比較)所以這次的項(xiàng)目中我采用了
DOM4J
作為
XML
解析工具。
在國(guó)內(nèi)比較流行的是使用
JDOM
作為解析器,兩者各擅其長(zhǎng),但
DOM4J
最大的特色是使用大量的接口,這也是它被認(rèn)為比
JDOM
靈活的主要原因。大師不是說(shuō)過(guò)么,
“
面向接口編程
”
。目前使用
DOM4J
的已經(jīng)越來(lái)越多。如果你善于使用
JDOM
,不妨繼續(xù)用下去,只看看本篇文章作為了解與比較,如果你正要采用一種解析器,不如就用
DOM4J
吧。
它的主要接口都在
org.dom4j
這個(gè)包里定義:
Attribute
|
Attribute
定義了
XML
的屬性
|
Branch
|
Branch
為能夠包含子節(jié)點(diǎn)的節(jié)點(diǎn)如
XML
元素
(Element)
和文檔
(Docuemnts)
定義了一個(gè)公共的行為,
|
CDATA
|
CDATA
定義了
XML CDATA
區(qū)域
|
CharacterData
|
CharacterData
是一個(gè)標(biāo)識(shí)借口,標(biāo)識(shí)基于字符的節(jié)點(diǎn)。如
CDATA
,
Comment, Text
.
|
Comment
|
Comment
定義了
XML
注釋的行為
|
Document
|
定義了
XML
文檔
|
DocumentType
|
DocumentType
定義
XML DOCTYPE
聲明
|
Element
|
Element
定義
XML
元素
|
ElementHandler
|
ElementHandler
定義了
Element
對(duì)象的處理器
|
ElementPath
|
被
ElementHandler
使用,用于取得當(dāng)前正在處理的路徑層次信息
|
Entity
|
Entity
定義
XML entity
|
Node
|
Node
為所有的
dom4j
中
XML
節(jié)點(diǎn)
定義了多態(tài)行為
|
NodeFilter
|
NodeFilter
定義了在
dom4j
節(jié)點(diǎn)中產(chǎn)生的一個(gè)濾鏡或謂詞的行為(
predicate
)
|
ProcessingInstruction
|
ProcessingInstruction
定義
XML
處理指令
.
|
Text
|
Text
定義
XML
文本節(jié)點(diǎn)
.
|
Visitor
|
Visitor
用于實(shí)現(xiàn)
Visitor
模式
.
|
XPath
|
XPath
在分析一個(gè)字符串后會(huì)提供一個(gè)
XPath
表達(dá)式
|
看名字大致就知道它們的涵義如何了。
要想弄懂這套接口,關(guān)鍵的是要明白接口的繼承關(guān)系:
一目了然,很多事情都清楚了。大部分都是由
Node
繼承來(lái)的。知道這些關(guān)系,將來(lái)寫(xiě)程序就不會(huì)出現(xiàn)
ClassCastException
了。
下面給出一些例子(部分摘自
DOM4J
自帶的文檔),簡(jiǎn)單說(shuō)一下如何使用。
1.?????????????
讀取并解析
XML
文檔:
讀寫(xiě)
XML
文檔主要依賴(lài)于
org.dom4j.io
包,其中提供
DOMReader
和
SAXReader
兩類(lèi)不同方式,而調(diào)用方式是一樣的。這就是依靠接口的好處。
?
??? //
從文件讀取
XML
,輸入文件名,返回
XML
文檔
??? publicDocumentread(StringfileName)throwsMalformedURLException,DocumentException{
?????? SAXReaderreader=newSAXReader();
?????? Documentdocument=reader.read(newFile(fileName));
?????? returndocument;
??? }
?
|
其中,
reader
的
read
方法是重載的,可以從
InputStream, File, Url
等多種不同的源來(lái)讀取。得到的
Document
對(duì)象就帶表了整個(gè)
XML
。
根據(jù)本人自己的經(jīng)驗(yàn),讀取的字符編碼是按照
XML
文件頭定義的編碼來(lái)轉(zhuǎn)換。如果遇到亂碼問(wèn)題,注意要把各處的編碼名稱(chēng)保持一致即可。
2.???
取得
Root
節(jié)點(diǎn)
讀取后的第二步,就是得到
Root
節(jié)點(diǎn)。熟悉
XML
的人都知道,一切
XML
分析都是從
Root
元素開(kāi)始的。
?
?
public
Element
getRootElement(Document
doc){
?????? returndoc.getRootElement();
??? }
?
|
3.???
遍歷
XML
樹(shù)
DOM4J
提供至少
3
種遍歷節(jié)點(diǎn)的方法:
1)
枚舉
(Iterator)
?
??? //
枚舉所有子節(jié)點(diǎn)
??? for
(
Iterator
i
=
root.elementIterator();
i.hasNext();
)
{
?????? Elementelement=(Element)i.next();
?????? // do something
??? }
??? //
枚舉名稱(chēng)為
foo
的節(jié)點(diǎn)
??? for
(
Iterator
i
=
root.elementIterator(
foo
);
i.hasNext();)
{
?????? Elementfoo=(Element)i.next();
?????? // do something
??? }
??? //
枚舉屬性
??? for
(
Iterator
i
=
root.attributeIterator();
i.hasNext();
)
{
?????? Attributeattribute=(Attribute)i.next();
?????? // do something
???
}
|
2)
遞歸
遞歸也可以采用
Iterator
作為枚舉手段,但文檔中提供了另外的做法
?
??? publicvoidtreeWalk(){
?????? treeWalk(getRootElement());
??? }
??? publicvoidtreeWalk(Elementelement){
?????? for(inti=0,size=element.nodeCount();i<size;i++)??? {
?????????? Nodenode=element.node(i);
?????????? if(nodeinstanceofElement){
????????????? treeWalk((Element)node);
?????????? }else{// do something....
?????????? }
?????? }
}
?
|
3) Visitor
模式
最令人興奮的是
DOM4J
對(duì)
Visitor
的支持,這樣可以大大縮減代碼量,并且清楚易懂。了解設(shè)計(jì)模式的人都知道,
Visitor
是
GOF
設(shè)計(jì)模式之一。其主要原理就是兩種類(lèi)互相保有對(duì)方的引用,并且一種作為
Visitor
去訪問(wèn)許多
Visitable
。我們來(lái)看
DOM4J
中的
Visitor
模式
(
快速文檔中沒(méi)有提供
)
只需要自定一個(gè)類(lèi)實(shí)現(xiàn)
Visitor
接口即可。
?
????
? publicclassMyVisitorextendsVisitorSupport{
?????? ??? publicvoidvisit(Elementelement){
?????????? ??? System.out.println(element.getName());
?????? ??? }
???
???
?? public
void
visit(Attribute
attr){
?????????? ??? System.out.println(attr.getName());
?????? ??? }
???????
}
?
???????
調(diào)用:
? root.accept(new MyVisitor())
|
??? Visitor
接口提供多種
Visit()
的重載,根據(jù)
XML
不同的對(duì)象,將采用不同的方式來(lái)訪問(wèn)。上面是給出的
Element
和
Attribute
的簡(jiǎn)單實(shí)現(xiàn),一般比較常用的就是這兩個(gè)。
VisitorSupport
是
DOM4J
提供的默認(rèn)適配器,
Visitor
接口的
Default Adapter
模式,這個(gè)模式給出了各種
visit(*)
的空實(shí)現(xiàn),以便簡(jiǎn)化代碼。
???
注意,這個(gè)
Visitor
是自動(dòng)遍歷所有子節(jié)點(diǎn)的。如果是
root.accept(MyVisitor)
,將遍歷子節(jié)點(diǎn)。我第一次用的時(shí)候,認(rèn)為是需要自己遍歷,便在遞歸中調(diào)用
Visitor
,結(jié)果可想而知。
4. XPath
支持
??? DOM4J
對(duì)
XPath
有良好的支持,如訪問(wèn)一個(gè)節(jié)點(diǎn),可直接用
XPath
選擇。
?
?? publicvoidbar(Documentdocument){
?????? ?Listlist=document.selectNodes(//foo/bar);
?????? ?Nodenode=document.selectSingleNode(//foo/bar/author);
?????? ?Stringname=node.valueOf(@name);
??? ?}
?
|
???
例如,如果你想查找
XHTML
文檔中所有的超鏈接,下面的代碼可以實(shí)現(xiàn):
?
??? publicvoidfindLinks(Documentdocument)throwsDocumentException{
?????? ?Listlist=document.selectNodes(//a/@href);
?????? ?for(Iteratoriter=list.iterator();iter.hasNext();){
?????????? ?Attributeattribute=(Attribute)iter.next();
?????????? ?Stringurl=attribute.getValue();
?????? ?}
??? ?}
?
|
5.
字符串與
XML
的轉(zhuǎn)換
有時(shí)候經(jīng)常要用到字符串轉(zhuǎn)換為
XML
或反之,
?
???
// XML
轉(zhuǎn)字符串
Document
document
=
...;
??? Stringtext=document.asXML();
//
字符串轉(zhuǎn)
XML
??? Stringtext=<person> <name>James</name> </person>;
??? Documentdocument=DocumentHelper.parseText(text);
?
|
6
用
XSLT
轉(zhuǎn)換
XML
?
?? publicDocumentstyleDocument(
?????? Documentdocument,
?????? Stringstylesheet
??? )throwsException{
??? // load the transformer using JAXP
??? TransformerFactoryfactory=TransformerFactory.newInstance();
??? Transformertransformer=factory.newTransformer(
?????? newStreamSource(stylesheet)
??? );
??? // now lets style the given document
??? DocumentSourcesource=newDocumentSource(document);
??? DocumentResultresult=newDocumentResult();
??? transformer.transform(source,result);
??? // return the transformed document
??? DocumenttransformedDoc=result.getDocument();
??? returntransformedDoc;
}
?
|
7.
創(chuàng)建
XML
?
一般創(chuàng)建
XML
是寫(xiě)文件前的工作,這就像
StringBuffer
一樣容易。
?
??? publicDocumentcreateDocument(){
?????? Documentdocument=DocumentHelper.createDocument();
?????? Elementroot=document.addElement(root);
?????? Elementauthor1=
?????????? root
????????????? .addElement(author)
????????????? .addAttribute(name,James)
????????????? .addAttribute(location,UK)
????????????? .addText(James Strachan);
?????? Elementauthor2=
?????????? root
????????????? .addElement(author)
????????????? .addAttribute(name,Bob)
????????????? .addAttribute(location,US)
????????????? .addText(Bob McWhirter);
?????? returndocument;
??? }
?
|
8.
文件輸出
???
一個(gè)簡(jiǎn)單的輸出方法是將一個(gè)
Document
或任何的
Node
通過(guò)
write
方法輸出
?
??? FileWriter
out
=
new
FileWriter(
foo.xml
);
??? document.write(out);
?
|
?
如果你想改變輸出的格式,比如美化輸出或縮減格式,可以用
XMLWriter
類(lèi)
?
??? publicvoidwrite(Documentdocument)throwsIOException{
?????? //
指定文件
?????? XMLWriterwriter=newXMLWriter(
??? ?????? newFileWriter(output.xml)
?????? );
?????? writer.write(document);
?????? writer.close();
?????? //
美化格式
?????? OutputFormatformat=OutputFormat.createPrettyPrint();
?????? writer=newXMLWriter(System.out,format);
?????? writer.write(document);
?????? //
縮減格式
?????? format=OutputFormat.createCompactFormat();
?????? writer=newXMLWriter(System.out,format);
?????? writer.write(document);
??? }
?
|
如何,
DOM4J
夠簡(jiǎn)單吧,當(dāng)然,還有一些復(fù)雜的應(yīng)用沒(méi)有提到,如
ElementHandler
等。如果你動(dòng)心了,那就一起來(lái)用
DOM4J.
DOM4J
官方網(wǎng)站:
(
我老連不上
)
http://www.dom4j.org
DOM4J
下載
(SourceForge)
,最新版本為
1.4
http://sourceforge.net/projects/dom4j
參考資料:
DOM4J
文檔
Java
中的
XML
:
文檔模型,第一部分:性能
http://www-900.ibm.com/developerWorks/cn/xml/x-injava/index.shtml
Java
中的
XML
:
Java
文檔模型的用法
http://www-900.ibm.com/developerWorks/cn/xml/x-injava2/index.shtml
Java XML API
漫談
by robbin
http://www.hibernate.org.cn:8000/137.html