?
本文主要討論了用 dom4j 解析 XML 的基礎(chǔ)問(wèn)題,包括建立 XML 文檔,添加、修改、刪除節(jié)點(diǎn),以及格式化(美化)輸出和中文問(wèn)題。可作為 dom4j 的入門資料。
?
1.
下載與安裝
?
dom4j 是 sourceforge.net 上的一個(gè)開源項(xiàng)目,主要用于對(duì) XML 的解析。從 2001 年 7 月發(fā)布第一版以來(lái),已陸續(xù)推出多個(gè)版本,目前最高版本為 1.5 。
dom4j 專門針對(duì) Java 開發(fā),使用起來(lái)非常簡(jiǎn)單、直觀,在 Java 界, dom4j 正迅速普及。
?
可以到 http://sourceforge.net/projects/dom4j 下載其最新版。
?
dom4j1.5 的完整版大約 13M ,是一個(gè)名為 dom4j-1.5.zip 的壓縮包,解壓后有一個(gè) dom4j-1.5.jar 文件,這就是應(yīng)用時(shí)需要引入的類包,另外還有一個(gè) jaxen-1.1-beta-4.jar 文件,一般也需要引入,否則執(zhí)行時(shí)可能拋 java.lang.NoClassDefFoundError: org/jaxen/JaxenException 異常,其他的包可以選擇用之。
?
2.
示例
XML
文檔(
holen.xml
)
?
為了述說(shuō)方便,先看一個(gè) XML 文檔,之后的操作均以此文檔為基礎(chǔ)。
?
holen.xml |
<?xml version="1.0" encoding="UTF-8"?> <books> ?????? <!--This is a test for dom4j, holen, 2004.9.11--> ?????? <book show="yes"> ????????????? <title>Dom4j Tutorials</title> ?????? </book> ?????? <book show="yes"> ????????????? <title>Lucene Studing</title> ?????? </book> ?????? <book show="no"> ????????????? <title>Lucene in Action</title> ?????? </book> ?????? <owner>O'Reilly</owner> </books> |
?
這是一個(gè)很簡(jiǎn)單的 XML 文檔,場(chǎng)景是一個(gè)網(wǎng)上書店,有很多書,每本書有兩個(gè)屬性,一個(gè)是書名 [title] ,一個(gè)為是否展示 [show] ,最后還有一項(xiàng)是這些書的擁有者 [owner] 信息。
?
3.
建立一個(gè)
XML
文檔
?
? |
???
/**
???
?
*
建立一個(gè)
XML
文檔
,
文檔名由輸入屬性決定
???
?
*
@param
filename
需建立的文件名
???
?
*
@return
返回操作結(jié)果
,
0
表失敗
,
1
表成功
???
?
*/
???
public
int
createXMLFile(String
filename){
??????
/**
返回操作結(jié)果
,
0
表失敗
,
1
表成功
*/
??????
int
returnValue
=
0;
??????
/**
建立
document
對(duì)象
*/
??????
Document
document
=
DocumentHelper.createDocument();
??????
/**
建立
XML
文檔的根
books
*/
??????
Element
booksElement
=
document.addElement(
"books"
);
??????
/**
加入一行注釋
*/
??????
booksElement.addComment(
"This is a test for dom4j, holen, 2004.9.11"
);
??????
/**
加入第一個(gè)
book
節(jié)點(diǎn)
*/
??????
Element
bookElement
=
booksElement.addElement(
"book"
);
??????
/**
加入
show
屬性內(nèi)容
*/
??????
bookElement.addAttribute(
"show"
,
"yes"
);
??????
/**
加入
title
節(jié)點(diǎn)
*/
??????
Element
titleElement
=
bookElement.addElement(
"title"
);
??????
/**
為
title
設(shè)置內(nèi)容
*/
??????
titleElement.setText(
"Dom4j Tutorials"
);
??????
??????
/**
類似的完成后兩個(gè)
book
*/
??????
bookElement
=
booksElement.addElement(
"book"
);
??????
bookElement.addAttribute(
"show"
,
"yes"
);
??????
titleElement
=
bookElement.addElement(
"title"
);
??????
titleElement.setText(
"Lucene Studing"
);
??????
bookElement
=
booksElement.addElement(
"book"
);
??????
bookElement.addAttribute(
"show"
,
"no"
);
??????
titleElement
=
bookElement.addElement(
"title"
);
??????
titleElement.setText(
"Lucene in Action"
);
??????
??????
/**
加入
owner
節(jié)點(diǎn)
*/
??????
Element
ownerElement
=
booksElement.addElement(
"owner"
);
??????
ownerElement.setText(
"O'Reilly"
);
??????
??????
try
{
??????????
/**
將
document
中的內(nèi)容寫入文件中
*/
??????????
XMLWriter
writer
=
new
XMLWriter(
new
FileWriter(
new
File(filename)));
??????????
writer.write(document);
??????????
writer.close();
??????????
/**
執(zhí)行成功
,
需返回
1
*/
??????????
returnValue
=
1;
??????
}
catch
(Exception
ex){
??????????
ex.printStackTrace();
??????
}
?????????????
??????
return
returnValue;
??? } |
?
說(shuō)明:
Document
document
=
DocumentHelper.createDocument();
通過(guò)這句定義一個(gè) XML 文檔對(duì)象。
?
Element booksElement = document.addElement("books");
通過(guò)這句定義一個(gè) XML 元素,這里添加的是根節(jié)點(diǎn)。
Element
有幾個(gè)重要的方法:
l????????
addComment
:添加注釋
l????????
addAttribute
:添加屬性
l????????
addElement
:添加子元素
?
最后通過(guò) XMLWriter 生成物理文件,默認(rèn)生成的 XML 文件排版格式比較亂,可以通過(guò) OutputFormat 類的 createCompactFormat() 方法或 createPrettyPrint() 方法格式化輸出,默認(rèn)采用 createCompactFormat() 方法,顯示比較緊湊,這點(diǎn)將在后面詳細(xì)談到。
?
生成后的 holen.xml 文件內(nèi)容如下:
?
? |
<?xml version="1.0" encoding="UTF-8"?> <books><!--This is a test for dom4j, holen, 2004.9.11--><book show="yes"><title>Dom4j Tutorials</title></book><book show="yes"><title>Lucene Studing</title></book><book show="no"><title>Lucene in Action</title></book><owner>O'Reilly</owner></books> |
?
4.
修改
XML
文檔
?
有三項(xiàng)修改任務(wù),依次為:
l???????? 如果 book 節(jié)點(diǎn)中 show 屬性的內(nèi)容為 yes, 則修改成 no
l???????? 把 owner 項(xiàng)內(nèi)容改為 Tshinghua ,并添加 date 節(jié)點(diǎn)
l???????? 若 title 內(nèi)容為 Dom4j Tutorials, 則刪除該節(jié)點(diǎn)
?
? |
???
/**
???
?
*
修改
XML
文件中內(nèi)容
,
并另存為一個(gè)新文件
???
?
*
重點(diǎn)掌握
dom4j
中如何添加節(jié)點(diǎn)
,
修改節(jié)點(diǎn)
,
刪除節(jié)點(diǎn)
???
?
*
@param
filename
修改對(duì)象文件
???
?
*
@param
newfilename
修改后另存為該文件
???
?
*
@return
返回操作結(jié)果
,
0
表失敗
,
1
表成功
???
?
*/
???
public
int
ModiXMLFile(String
filename,String
newfilename){
??????
int
returnValue
=
0;
??????
try
{
??????????
SAXReader
saxReader
=
new
SAXReader();
??????????
Document
document
=
saxReader.read(
new
File(filename));
??????????
/**
修改內(nèi)容之一
:
如果
book
節(jié)點(diǎn)中
show
屬性的內(nèi)容為
yes,
則修改成
no
*/
??????????
/**
先用
xpath
查找對(duì)象
*/
??????????
List
list
=
document.selectNodes(
"/books/book/@show"
);
??????????
Iterator
iter
=
list.iterator();
??????????
while
(iter.hasNext()){
?????????????
Attribute
attribute
=
(Attribute)iter.next();
?????????????
if
(attribute.getValue().equals(
"yes"
)){
?????????????????
attribute.setValue(
"no"
);
?????????????
}
??
??????????
}
??????????
??????????
/**
??????????
?
*
修改內(nèi)容之二
:
把
owner
項(xiàng)內(nèi)容改為
Tshinghua
??????????
?
*
并在
owner
節(jié)點(diǎn)中加入
date
節(jié)點(diǎn)
,date
節(jié)點(diǎn)的內(nèi)容為
2004
-
09
-
11,
還為
date
節(jié)點(diǎn)添加一個(gè)屬性
type
??????????
?
*/
??????????
list
=
document.selectNodes(
"/books/owner"
);
??????
???
iter
=
list.iterator();
??????????
if
(iter.hasNext()){
?????????????
Element
ownerElement
=
(Element)iter.next();
?????????????
ownerElement.setText(
"Tshinghua"
);
?????????????
Element
dateElement
=
ownerElement.addElement(
"date"
);
?????????????
dateElement.setText(
"2004-09-11"
);
?????????????
dateElement.addAttribute(
"type"
,
"Gregorian calendar"
);
??????????
}
??????????
??????????
/**
修改內(nèi)容之三
:
若
title
內(nèi)容為
Dom4j
Tutorials,
則刪除該節(jié)點(diǎn)
*/
??????????
list
=
document.selectNodes(
"/books/book"
);
??????????
iter
=
list.iterator();
??????????
while
(iter.hasNext()){
?????????????
Element
bookElement
=
(Element)iter.next();
?????????????
Iterator
iterator
=
bookElement.elementIterator(
"title"
);
??????????
???
while
(iterator.hasNext()){
?????????????????
Element
titleElement=(Element)iterator.next();
?????????????????
if
(titleElement.getText().equals(
"Dom4j Tutorials"
)){
????????????????????
bookElement.remove(titleElement);
?????????????????
}
?????????????
}
??????????
}
?????????
??????????
??????????
try
{
?????????????
/**
將
document
中的內(nèi)容寫入文件中
*/
?????????????
XMLWriter
writer
=
new
XMLWriter(
new
FileWriter(
new
File(newfilename)));
?????????????
writer.write(document);
?????????????
writer.close();
?????????????
/**
執(zhí)行成功
,
需返回
1
*/
?????????????
returnValue
=
1;
??????????
}
catch
(Exception
ex){
?????????????
ex.printStackTrace();
??????????
}
??????????
??????
}
catch
(Exception
ex){
??????????
ex.printStackTrace();
??????
}
??????
return
returnValue;
???
}
??? |
?
說(shuō)明:
List list = document.selectNodes("/books/book/@show" );
list = document.selectNodes("/books/book");
上述代碼通過(guò) xpath 查找到相應(yīng)內(nèi)容。
?
通過(guò)
setValue
()
、
setText
()
修改節(jié)點(diǎn)內(nèi)容。
?
通過(guò) remove () 刪除節(jié)點(diǎn)或?qū)傩浴?/span>
?
5.
格式化輸出和指定編碼
?
默認(rèn)的輸出方式為緊湊方式,默認(rèn)編碼為 UTF-8 ,但對(duì)于我們的應(yīng)用而言,一般都要用到中文,并且希望顯示時(shí)按自動(dòng)縮進(jìn)的方式的顯示,這就需用到 OutputFormat 類。
?
? |
???
???
/**
???
?
*
格式化
XML
文檔
,
并解決中文問(wèn)題
???
?
*
@param
filename
???
?
*
@return
???
?
*/
???
public
int
formatXMLFile(String
filename){
??????
int
returnValue
=
0;
??????
try
{
??????????
SAXReader
saxReader
=
new
SAXReader();
??????????
Document
document
=
saxReader.read(
new
File(filename));
??????????
XMLWriter
writer =
null
;
??????????
/**
格式化輸出
,
類型
IE
瀏覽一樣
*/
??????????
OutputFormat
format
=
OutputFormat.createPrettyPrint();
??????????
/**
指定
XML
編碼
*/
??????????
format.setEncoding(
"GBK"
);
??????????
writer=
new
XMLWriter(
new
FileWriter(
new
File(filename)),format);
??????????
writer.write(document);
??????????
writer.close();
?????
??????????
/**
執(zhí)行成功
,
需返回
1
*/
??????????
returnValue
=
1;
????
??????
}
catch
(Exception
ex){
??????????
ex.printStackTrace();
??????
}
??????
return
returnValue;
??? } |
?
說(shuō)明:
?
OutputFormat format = OutputFormat.createPrettyPrint();
這句指定了格式化的方式為縮進(jìn)式,則非緊湊式。
?
format.setEncoding("GBK");
指定編碼為 GBK 。
?
XMLWriter writer = new XMLWriter(new FileWriter(new File(filename)),format);
這與前面兩個(gè)方法相比,多加了一個(gè) OutputFormat 對(duì)象,用于指定顯示和編碼方式。
?
6.
完整的類代碼
?
前面提出的方法都是零散的,下面給出完整類代碼。
?
Dom4jDemo.java |
package
com.holen.dom4j;
?
import
java.io.File;
import
java.io.FileWriter;
import
java.util.Iterator;
import
java.util.List;
?
import
org.dom4j.Attribute;
import
org.dom4j.Document;
import
org.dom4j.DocumentHelper;
import
org.dom4j.Element;
import
org.dom4j.io.OutputFormat;
import
org.dom4j.io.SAXReader;
import
org.dom4j.io.XMLWriter;
?
/**
?
*
@author
Holen
Chen
?
*/
public
class
Dom4jDemo
{
???
???
public
Dom4jDemo()
{
???
}
?
???
public
int
createXMLFile(String
filename){
…}
???
public
int
ModiXMLFile(String
filename,String
newfilename){
…}
???
public
int
formatXMLFile(String
filename){
…}
?
???
public
static
void
main(String[]
args)
{
??????
Dom4jDemo
temp
=
new
Dom4jDemo();
??????
System.out.println(temp.createXMLFile(
"d://holen.xml"
));
???
???
System.out.println(temp.ModiXMLFile(
"d://holen.xml"
,
"d://holen2.xml"
));
??????
System.out.println(temp.formatXMLFile(
"d://holen2.xml"
));
???
}
} |
?
說(shuō)明:
main() 方法中依次調(diào)用三個(gè)方法,第一個(gè)方法用于生成 holen.xml ,第二個(gè)方法用于修改 holen.xml ,并且修改后的內(nèi)容另存為 holen2.xml ,第三個(gè)方法將 holen2.xml 格式化縮進(jìn)式輸出,并指定編碼方式為 GBK 。
?
重新格式化后 holen2.xml 文件顯示如下:
?
項(xiàng)目視圖供參考:
?
7.
總結(jié)
?
總的來(lái)說(shuō), dom4j 的使用是很簡(jiǎn)單的,而且與 Java 結(jié)合緊密,功能強(qiáng)大。