Dom4j也可以很方便完成XML文檔的創建、元素的修改、文檔的查詢遍歷等,但dom4j稍比jdom復雜一點,不過在大片文檔的情況下dom4j的性能要不jdom好。
### 準備
首先,提供相關的jar包
Dom4jjar包下載:
[http://sourceforge.net/projects/dom4j/files/dom4j-2.0.0-ALPHA-2/](http://sourceforge.net/projects/dom4j/files/dom4j-2.0.0-ALPHA-2/)
jaxenjar下載:
[http://repo1.maven.org/maven2/jaxen/jaxen/1.1.1/jaxen-1.1.1.jar](http://repo1.maven.org/maven2/jaxen/jaxen/1.1.1/jaxen-1.1.1.jar)
和dom4j依賴或相關的jar:
[http://dom4j.sourceforge.net/dependencies.html](http://dom4j.sourceforge.net/dependencies.html)
Junit-jar下載:
[http://ebr.springsource.com/repository/app/bundle/version/download?name=com.springsource.org.junit&version=4.8.1&type=binary](http://ebr.springsource.com/repository/app/bundle/version/download?name=com.springsource.org.junit&version=4.8.1&type=binary)
?
其次,準備測試案例的部分代碼:
~~~
package com.hoo.test;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.QName;
import org.dom4j.dom.DOMAttribute;
import org.dom4j.io.SAXReader;
import org.dom4j.tree.BaseElement;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* <b>function:</b> 使用Dom4j操作XML
* @author hoojo
* @createDate 2011-8-5 下午06:15:40
* @file DocumentTest.java
* @package com.hoo.test
* @project Dom4jTest
* @blog http://blog.csdn.net/IBM_hoojo
* @email hoojo_@126.com
* @version 1.0
*/
public class DocumentTest {
private SAXReader reader = null;
@Before
public void init() {
reader = new SAXReader();
}
@After
public void destory() {
reader = null;
System.gc();
}
public void fail(Object o) {
if (o != null)
System.out.println(o);
}
}
~~~
### 創建一篇XML文檔
文檔格式如下:
~~~
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<!--An XML Catalog-->
<?target instruction?>
<journal title="XML Zone" publisher="IBM developerWorks">
<article level="Intermediate" date="December-2001">
<title>Java configuration with XML Schema</title>
<author>
<firstname>Marcello</firstname>
<lastname>Vitaletti</lastname>
</author>
</article>
</journal>
</catalog>
~~~
創建文檔代碼如下:
~~~
/**
* <b>function:</b>創建文檔
* @author hoojo
* @createDate 2011-8-5 下午06:18:18
*/
@Test
public void createDocument() {
//創建一篇文檔
Document doc = DocumentHelper.createDocument();
//添加一個元素
Element root = doc.addElement("catalog");
//為root元素添加注釋
root.addComment("An XML Catalog");
//添加標記
root.addProcessingInstruction("target", "instruction");
//創建元素
Element journalEl = new BaseElement("journal");
//添加屬性
journalEl.addAttribute("title", "XML Zone");
journalEl.addAttribute("publisher", "IBM developerWorks");
root.add(journalEl);
//添加元素
Element articleEl = journalEl.addElement("article");
articleEl.addAttribute("level", "Intermediate");
articleEl.addAttribute("date", "December-2001");
Element titleEl = articleEl.addElement("title");
//設置文本內容
titleEl.setText("Java configuration with XML Schema");
//titleEl.addText("Java configuration with XML Schema");
Element authorEl = articleEl.addElement("author");
authorEl.addElement("firstname").setText("Marcello");
authorEl.addElement("lastname").addText("Vitaletti");
//可以使用 addDocType() 方法添加文檔類型說明。
doc.addDocType("catalog", null,"file://c:/Dtds/catalog.dtd");
fail(doc.getRootElement().getName());
//將xml轉換成文本
fail(doc.asXML());
//寫入到文件
/*XMLWriter output;
try {
output = new XMLWriter(new FileWriter(new File("file/catalog.xml")));
output.write(doc);
output.close();
} catch (IOException e) {
e.printStackTrace();
}*/
}
~~~
DocumentHelper是一個文檔助手類(工具類),它可以完成文檔、元素、文本、屬性、注釋、CDATA、Namespace、XPath的創建,以及利用XPath完成文檔的遍歷和將文本轉換成Document;
parseText完成將xml字符串轉換成Doc的功能
<table border="1" cellpadding="0" cellspacing="0"><tbody><tr><td valign="top"><p><span style="font-size:13px">Document doc = DocumentHelper.parseText("<root></root>");</span></p></td></tr></tbody></table>
?
createDocument創建一個文檔
<table border="1" cellpadding="0" cellspacing="0" height="32" width="359"><tbody><tr><td valign="top"><p><span style="font-size:13px">Document doc = DocumentHelper.createDocument();</span></p></td></tr></tbody></table>
如果帶參數就會創建一個帶有根元素的文檔
createElement創建一個元素
<table border="1" cellpadding="0" cellspacing="0" height="32" width="357"><tbody><tr><td valign="top"><p><span style="font-size:13px">Element el = DocumentHelper.createElement("el");</span></p></td></tr></tbody></table>
Document的addElement方法可以給當前文檔添加一個子元素
<table border="1" cellpadding="0" cellspacing="0" height="32" width="355"><tbody><tr><td valign="top"><p><span style="font-size:13px">Element root = doc.addElement("catalog");</span></p></td></tr></tbody></table>
addComment方法可以添加一段注釋
<table border="1" cellpadding="0" cellspacing="0" height="32" width="351"><tbody><tr><td valign="top"><p><span style="font-size:13px">root.addComment("An XML Catalog");</span></p></td></tr></tbody></table>
為root元素添加一段注釋
addProcessingInstruction添加一個標記
<table border="1" cellpadding="0" cellspacing="0" height="32" width="348"><tbody><tr><td valign="top"><p><span style="font-size:13px">root.addProcessingInstruction("target", "instruction");</span></p></td></tr></tbody></table>
為root元素添加一個標記
newBaseElement可以創建一個元素
<table border="1" cellpadding="0" cellspacing="0" height="32" width="350"><tbody><tr><td valign="top"><p><span style="font-size:13px">Element journalEl = new BaseElement("journal");</span></p></td></tr></tbody></table>
addAttribute添加屬性
<table border="1" cellpadding="0" cellspacing="0" height="32" width="350"><tbody><tr><td valign="top"><p><span style="font-size:13px">journalEl.addAttribute("title", "XML Zone");</span></p></td></tr></tbody></table>
add添加一個元素
<table border="1" cellpadding="0" cellspacing="0" height="32" width="349"><tbody><tr><td valign="top"><p><span style="font-size:13px">root.add(journalEl);</span></p></td></tr></tbody></table>
將journalEl元素添加到root元素中
addElement添加一個元素,并返回當前元素
<table border="1" cellpadding="0" cellspacing="0" height="32" width="346"><tbody><tr><td valign="top"><p><span style="font-size:13px">Element articleEl = journalEl.addElement("article");</span></p></td></tr></tbody></table>
給journalEl元素添加一個子元素article
setText、addText可以設置元素的文本
<table border="1" cellpadding="0" cellspacing="0" height="56" width="349"><tbody><tr><td valign="top"><p><span style="font-size:13px">authorEl.addElement("firstname").setText("Marcello");</span></p><p><span style="font-size:13px">authorEl.addElement("lastname").addText("Vitaletti");</span></p></td></tr></tbody></table>
addDocType可以設置文檔的DOCTYPE
<table border="1" cellpadding="0" cellspacing="0"><tbody><tr><td valign="top"><p><span style="font-size:13px">doc.addDocType("catalog", null,"file://c:/Dtds/catalog.dtd");</span></p></td></tr></tbody></table>
asXML可以將文檔或元素轉換成一段xml字符串
<table border="1" cellpadding="0" cellspacing="0" height="56" width="344"><tbody><tr><td valign="top"><p><span style="font-size:13px">doc.asXML();</span></p><p><span style="font-size:13px">root.asXML();</span></p></td></tr></tbody></table>
XMLWriter類可以把文檔寫入到文件中
<table border="1" cellpadding="0" cellspacing="0"><tbody><tr><td valign="top"><p><span style="font-size:13px">output = new XMLWriter(new FileWriter(new File("file/catalog.xml")));</span></p><p><span style="font-size:13px">output.write(doc);</span></p><p><span style="font-size:13px">output.close();</span></p></td></tr></tbody></table>
### 修改XML文檔內容
~~~
/**
* <b>function:</b> 修改XML內容
* @author hoojo
* @createDate 2011-8-9 下午03:37:04
*/
@SuppressWarnings("unchecked")
@Test
public void modifyDoc() {
try {
Document doc = reader.read(new File("file/catalog.xml"));
//修改屬性內容
List list = doc.selectNodes("//article/@level");
Iterator<Attribute> iter = list.iterator();
while (iter.hasNext()) {
Attribute attr = iter.next();
fail(attr.getName() + "#" + attr.getValue() + "#" + attr.getText());
if ("Intermediate".equals(attr.getValue())) {
//修改屬性值
attr.setValue("Introductory");
fail(attr.getName() + "#" + attr.getValue() + "#" + attr.getText());
}
}
list = doc.selectNodes("//article/@date");
iter = list.iterator();
while (iter.hasNext()) {
Attribute attr = iter.next();
fail(attr.getName() + "#" + attr.getValue() + "#" + attr.getText());
if ("December-2001".equals(attr.getValue())) {
//修改屬性值
attr.setValue("December-2011");
fail(attr.getName() + "#" + attr.getValue() + "#" + attr.getText());
}
}
//修改節點內容
list = doc.selectNodes("//article");
Iterator<Element> it = list.iterator();
while (it.hasNext()) {
Element el = it.next();
fail(el.getName() + "#" + el.getText() + "#" + el.getStringValue());
//修改title元素
Iterator<Element> elIter = el.elementIterator("title");
while(elIter.hasNext()) {
Element titleEl = elIter.next();
fail(titleEl.getName() + "#" + titleEl.getText() + "#" + titleEl.getStringValue());
if ("Java configuration with XML Schema".equals(titleEl.getTextTrim())) {
//修改元素文本值
titleEl.setText("Modify the Java configuration with XML Schema");
fail(titleEl.getName() + "#" + titleEl.getText() + "#" + titleEl.getStringValue());
}
}
}
//修改節點子元素內容
list = doc.selectNodes("//article/author");
it = list.iterator();
while (it.hasNext()) {
Element el = it.next();
fail(el.getName() + "#" + el.getText() + "#" + el.getStringValue());
List<Element> childs = el.elements();
for (Element e : childs) {
fail(e.getName() + "#" + e.getText() + "#" + e.getStringValue());
if ("Marcello".equals(e.getTextTrim())) {
e.setText("Ayesha");
} else if ("Vitaletti".equals(e.getTextTrim())) {
e.setText("Malik");
}
fail(e.getName() + "#" + e.getText() + "#" + e.getStringValue());
}
}
//寫入到文件
/*XMLWriter output = new XMLWriter(new FileWriter(new File("file/catalog-modified.xml")));
output.write(doc);
output.close();*/
} catch (DocumentException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
~~~
reader.read(new File("file/catalog.xml"));讀取指定xml文件內容到文檔中;
selectNodes是XPath的查詢方法,完成xml文檔的查詢,傳遞xpath路徑。其使用方法可以參考jdom的xpath的使用方法:[http://www.cnblogs.com/hoojo/archive/2011/08/11/2134638.html](http://www.cnblogs.com/hoojo/archive/2011/08/11/2134638.html)
getName獲取元素標簽名稱、getValue、getText獲取值、文本內容;
elementIterator("title");獲取當前節點下所有的title元素,返回Iterator;
elements獲取下面所有的子元素,返回的是一個集合List;
### 顯示文檔相關信息
~~~
private String format(int i) {
String temp = "";
while (i > 0) {
temp += "--";
i--;
}
return temp;
}
/**
* <b>function:</b>遞歸顯示文檔內容
* @author hoojo
* @createDate 2011-8-9 下午03:43:45
* @param i
* @param els
*/
private void print(int i, List<Element> els) {
i++;
for (Element el : els) {
fail(format(i) + "##" + el.getName() + "#" + el.getTextTrim());
if (el.hasContent()) {
print(i, el.elements());
}
}
}
/**
* <b>function:</b>顯示文檔相關信息
* @author hoojo
* @createDate 2011-8-9 下午03:44:10
*/
@Test
public void printInfo() {
try {
Document doc = reader.read(new File("file/catalog.xml"));
fail("asXML: " + doc.asXML());
fail(doc.asXPathResult(new BaseElement("article")));
List<Node> list = doc.content();
for (Node node : list) {
fail("Node: " + node.getName() + "#" + node.getText() + "#" + node.getStringValue());
}
fail("-----------------------------");
print(0, doc.getRootElement().elements());
fail("getDocType: " + doc.getDocType());
fail("getNodeTypeName: " + doc.getNodeTypeName());
fail("getPath: " + doc.getRootElement().getPath());
fail("getPath: " + doc.getRootElement().getPath(new BaseElement("journal")));
fail("getUniquePath: " + doc.getRootElement().getUniquePath());
fail("getXMLEncoding: " + doc.getXMLEncoding());
fail("hasContent: " + doc.hasContent());
fail("isReadOnly: " + doc.isReadOnly());
fail("nodeCount: " + doc.nodeCount());
fail("supportsParent: " + doc.supportsParent());
} catch (DocumentException e) {
e.printStackTrace();
}
fail("getEncoding: " + reader.getEncoding());
fail("isIgnoreComments: " + reader.isIgnoreComments());
fail("isMergeAdjacentText: " + reader.isMergeAdjacentText());
fail("isStringInternEnabled: " + reader.isStringInternEnabled());
fail("isStripWhitespaceText: " + reader.isStripWhitespaceText());
fail("isValidating: " + reader.isValidating());
}
~~~
### 刪除文檔內容
~~~
/**
* <b>function:</b> 刪除節點內容
* @author hoojo
* @createDate 2011-8-9 下午03:47:44
*/
@Test
public void removeNode() {
try {
Document doc = reader.read(new File("file/catalog-modified.xml"));
fail("comment: " + doc.selectSingleNode("//comment()"));
//刪除注釋
doc.getRootElement().remove(doc.selectSingleNode("//comment()"));
Element node = (Element) doc.selectSingleNode("//article");
//刪除屬性
node.remove(new DOMAttribute(QName.get("level"), "Introductory"));
//刪除元素 節點
node.remove(doc.selectSingleNode("//title"));
//只能刪除下一級節點,不能超過一級;(需要在父元素的節點上刪除子元素)
Node lastNameNode = node.selectSingleNode("//lastname");
lastNameNode.getParent().remove(lastNameNode);
fail("Text: " + doc.selectObject("//*[text()='Ayesha']"));
Element firstNameEl = (Element)doc.selectObject("//firstname");
fail("Text: " + firstNameEl.selectSingleNode("text()"));
//刪除text文本
//firstNameEl.remove(firstNameEl.selectSingleNode("text()"));
//firstNameEl.remove(doc.selectSingleNode("//firstname/text()"));
firstNameEl.remove(doc.selectSingleNode("//*[text()='Ayesha']/text()"));
//刪除子元素author
//node.remove(node.selectSingleNode("//author"));
fail(doc.asXML());
} catch (Exception e) {
e.printStackTrace();
}
}
~~~
刪除注釋
<table border="1" cellpadding="0" cellspacing="0"><tbody><tr><td valign="top"><p><span style="font-size:13px">doc.getRootElement().remove(doc.selectSingleNode("//comment()"));</span></p></td></tr></tbody></table>
刪除root元素下面的注釋
刪除屬性
<table border="1" cellpadding="0" cellspacing="0"><tbody><tr><td valign="top"><p><span style="font-size:13px">node.remove(new DOMAttribute(QName.get("level"), "Introductory"));</span></p></td></tr></tbody></table>
刪除node節點中的名稱為level,其值為Introductory的屬性
刪除元素
<table border="1" cellpadding="0" cellspacing="0" height="32" width="401"><tbody><tr><td valign="top"><p><span style="font-size:13px">node.remove(doc.selectSingleNode("//title"));</span></p></td></tr></tbody></table>
刪除node節點下的title元素
刪除文本
<table border="1" cellpadding="0" cellspacing="0"><tbody><tr><td valign="top"><p><span style="font-size:13px">firstNameEl.remove(firstNameEl.selectSingleNode("text()"));</span></p><p><span style="font-size:13px">firstNameEl.remove(doc.selectSingleNode("//firstname/text()"));</span></p><p><span style="font-size:13px">firstNameEl.remove(doc.selectSingleNode("//*[text()='Ayesha']/text()"));</span></p></td></tr></tbody></table>
刪除firstNameEl的文本內容