?
本文主要討論了用 dom4j 解析 XML 的基礎問題,包括建立 XML 文檔,添加、修改、刪除節點,以及格式化(美化)輸出和中文問題??勺鳛?/span> dom4j 的入門資料。
?
1.
下載與安裝
?
dom4j 是 sourceforge.net 上的一個開源項目,主要用于對 XML 的解析。從 2001 年 7 月發布第一版以來,已陸續推出多個版本,目前最高版本為 1.5 。
dom4j 專門針對 Java 開發,使用起來非常簡單、直觀,在 Java 界, dom4j 正迅速普及。
?
可以到 http://sourceforge.net/projects/dom4j 下載其最新版。
?
dom4j1.5 的完整版大約 13M ,是一個名為 dom4j-1.5.zip 的壓縮包,解壓后有一個 dom4j-1.5.jar 文件,這就是應用時需要引入的類包,另外還有一個 jaxen-1.1-beta-4.jar 文件,一般也需要引入,否則執行時可能拋 java.lang.NoClassDefFoundError: org/jaxen/JaxenException 異常,其他的包可以選擇用之。
?
2.
示例
XML
文檔(
holen.xml
)
?
為了述說方便,先看一個 XML 文檔,之后的操作均以此文檔為基礎。
?
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> |
?
這是一個很簡單的 XML 文檔,場景是一個網上書店,有很多書,每本書有兩個屬性,一個是書名 [title] ,一個為是否展示 [show] ,最后還有一項是這些書的擁有者 [owner] 信息。
?
3.
建立一個
XML
文檔
?
? |
???
/**
???
?
*
建立一個
XML
文檔
,
文檔名由輸入屬性決定
???
?
*
@param
filename
需建立的文件名
???
?
*
@return
返回操作結果
,
0
表失敗
,
1
表成功
???
?
*/
???
public
int
createXMLFile(String
filename){
??????
/**
返回操作結果
,
0
表失敗
,
1
表成功
*/
??????
int
returnValue
=
0;
??????
/**
建立
document
對象
*/
??????
Document
document
=
DocumentHelper.createDocument();
??????
/**
建立
XML
文檔的根
books
*/
??????
Element
booksElement
=
document.addElement(
"books"
);
??????
/**
加入一行注釋
*/
??????
booksElement.addComment(
"This is a test for dom4j, holen, 2004.9.11"
);
??????
/**
加入第一個
book
節點
*/
??????
Element
bookElement
=
booksElement.addElement(
"book"
);
??????
/**
加入
show
屬性內容
*/
??????
bookElement.addAttribute(
"show"
,
"yes"
);
??????
/**
加入
title
節點
*/
??????
Element
titleElement
=
bookElement.addElement(
"title"
);
??????
/**
為
title
設置內容
*/
??????
titleElement.setText(
"Dom4j Tutorials"
);
??????
??????
/**
類似的完成后兩個
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
節點
*/
??????
Element
ownerElement
=
booksElement.addElement(
"owner"
);
??????
ownerElement.setText(
"O'Reilly"
);
??????
??????
try
{
??????????
/**
將
document
中的內容寫入文件中
*/
??????????
XMLWriter
writer
=
new
XMLWriter(
new
FileWriter(
new
File(filename)));
??????????
writer.write(document);
??????????
writer.close();
??????????
/**
執行成功
,
需返回
1
*/
??????????
returnValue
=
1;
??????
}
catch
(Exception
ex){
??????????
ex.printStackTrace();
??????
}
?????????????
??????
return
returnValue;
??? } |
?
說明:
Document
document
=
DocumentHelper.createDocument();
通過這句定義一個 XML 文檔對象。
?
Element booksElement = document.addElement("books");
通過這句定義一個 XML 元素,這里添加的是根節點。
Element
有幾個重要的方法:
l????????
addComment
:添加注釋
l????????
addAttribute
:添加屬性
l????????
addElement
:添加子元素
?
最后通過 XMLWriter 生成物理文件,默認生成的 XML 文件排版格式比較亂,可以通過 OutputFormat 類的 createCompactFormat() 方法或 createPrettyPrint() 方法格式化輸出,默認采用 createCompactFormat() 方法,顯示比較緊湊,這點將在后面詳細談到。
?
生成后的 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> |
?
4.
修改
XML
文檔
?
有三項修改任務,依次為:
l???????? 如果 book 節點中 show 屬性的內容為 yes, 則修改成 no
l???????? 把 owner 項內容改為 Tshinghua ,并添加 date 節點
l???????? 若 title 內容為 Dom4j Tutorials, 則刪除該節點
?
? |
???
/**
???
?
*
修改
XML
文件中內容
,
并另存為一個新文件
???
?
*
重點掌握
dom4j
中如何添加節點
,
修改節點
,
刪除節點
???
?
*
@param
filename
修改對象文件
???
?
*
@param
newfilename
修改后另存為該文件
???
?
*
@return
返回操作結果
,
0
表失敗
,
1
表成功
???
?
*/
???
public
int
ModiXMLFile(String
filename,String
newfilename){
??????
int
returnValue
=
0;
??????
try
{
??????????
SAXReader
saxReader
=
new
SAXReader();
??????????
Document
document
=
saxReader.read(
new
File(filename));
??????????
/**
修改內容之一
:
如果
book
節點中
show
屬性的內容為
yes,
則修改成
no
*/
??????????
/**
先用
xpath
查找對象
*/
??????????
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"
);
?????????????
}
??
??????????
}
??????????
??????????
/**
??????????
?
*
修改內容之二
:
把
owner
項內容改為
Tshinghua
??????????
?
*
并在
owner
節點中加入
date
節點
,date
節點的內容為
2004
-
09
-
11,
還為
date
節點添加一個屬性
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"
);
??????????
}
??????????
??????????
/**
修改內容之三
:
若
title
內容為
Dom4j
Tutorials,
則刪除該節點
*/
??????????
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
中的內容寫入文件中
*/
?????????????
XMLWriter
writer
=
new
XMLWriter(
new
FileWriter(
new
File(newfilename)));
?????????????
writer.write(document);
?????????????
writer.close();
?????????????
/**
執行成功
,
需返回
1
*/
?????????????
returnValue
=
1;
??????????
}
catch
(Exception
ex){
?????????????
ex.printStackTrace();
??????????
}
??????????
??????
}
catch
(Exception
ex){
??????????
ex.printStackTrace();
??????
}
??????
return
returnValue;
???
}
??? |
?
說明:
List list = document.selectNodes("/books/book/@show" );
list = document.selectNodes("/books/book");
上述代碼通過 xpath 查找到相應內容。
?
通過
setValue
()
、
setText
()
修改節點內容。
?
通過 remove () 刪除節點或屬性。
?
5.
格式化輸出和指定編碼
?
默認的輸出方式為緊湊方式,默認編碼為 UTF-8 ,但對于我們的應用而言,一般都要用到中文,并且希望顯示時按自動縮進的方式的顯示,這就需用到 OutputFormat 類。
?
? |
???
???
/**
???
?
*
格式化
XML
文檔
,
并解決中文問題
???
?
*
@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();
?????
??????????
/**
執行成功
,
需返回
1
*/
??????????
returnValue
=
1;
????
??????
}
catch
(Exception
ex){
??????????
ex.printStackTrace();
??????
}
??????
return
returnValue;
??? } |
?
說明:
?
OutputFormat format = OutputFormat.createPrettyPrint();
這句指定了格式化的方式為縮進式,則非緊湊式。
?
format.setEncoding("GBK");
指定編碼為 GBK 。
?
XMLWriter writer = new XMLWriter(new FileWriter(new File(filename)),format);
這與前面兩個方法相比,多加了一個 OutputFormat 對象,用于指定顯示和編碼方式。
?
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"
));
???
}
} |
?
說明:
main() 方法中依次調用三個方法,第一個方法用于生成 holen.xml ,第二個方法用于修改 holen.xml ,并且修改后的內容另存為 holen2.xml ,第三個方法將 holen2.xml 格式化縮進式輸出,并指定編碼方式為 GBK 。
?
重新格式化后 holen2.xml 文件顯示如下:
?
項目視圖供參考:
?
7.
總結
?
總的來說, dom4j 的使用是很簡單的,而且與 Java 結合緊密,功能強大。