# XML編程-DOM4J
### 基本概述
????dom4j是一個Java的XML?API,類似于jdom,用來讀寫XML文件的。dom4j是一個十分優秀的JavaXML?API,具有性能優異、功能強大和極其易使用的特點,同時它也是一個開放源代碼的軟件,可以在SourceForge上找到它。在IBM?developerWorks上面還可以找到一篇文章,對主流的Java?XML?API進行的性能、功能和易用性的評測,所以可以知道dom4j無論在哪個方面都是非常出色的。如今可以看到越來越多的Java軟件都在使用dom4j來讀寫XML,特別值得一提的是連Sun的JAXM也在用dom4j。這已經是必須使用的jar包,?Hibernate也用它來讀寫配置文件。
PS:DOM4J功能那么強大的原因之一就是它支持XPath技術,DOM4J也有相應的參考文檔,需要的可以自行搜索下載。
?
### 為什么會有DOM4J?
之前,博客里闡述的兩門技術,DOM和SAX技術,前者的缺點是耗費內存,后者的缺點是只能進行讀取操作,而DOM4J既可以提交效率,也可以進行crud操作。
PS:使用DOM4J需要導入相應基本JAR包,如果使用DOM4J的擴展功能,還需要導入擴展JAR包。
?
### DOM4J使用入門
### DOM4J獲得Document對象的三種方法
#### 1.讀取XML文件,獲得document對象(常用)? ? ? ? ? ??
~~~
SAXReader reader = new SAXReader();
Document?? document = reader.read(new File(“src/input.xml"));
~~~
#### 2.解析XML形式的文本,得到document對象
~~~
String text = "<members></members>";
Document document = DocumentHelper.parseText(text);
~~~
#### 3.主動創建document對象
~~~
Document document = DocumentHelper.createDocument();
//創建根節點
Element root = document.addElement("members");
~~~
PS:注意要導入相應JAR包。
### 節點對象
#### 1、獲取文檔的根節點
~~~
Element root = document.getRootElement();
~~~
#### 2、取得某個節點的子節點
~~~
Element element=node.element(“書名");
~~~
#### 3、取得節點的內容
~~~
String text1=node.getText();
String text2=node.getTextTrim(); // 去掉內容前面和后面的空格
~~~
#### 4、取得某節點下所有名為“member”的子節點,并進行遍歷?
~~~
List nodes = rootElm.elements("member");
for (Iterator it = nodes.iterator(); it.hasNext();) {
??? Element elm = (Element) it.next();
??? // do something
}
~~~
#### 5、對某節點下的所有子節點進行遍歷
~~~
for(Iterator it=root.elementIterator();it.hasNext();){
Element element = (Element) it.next();
?????? // do something
??? }
~~~
#### 6、在某節點下添加子節點
~~~
Element ageElm = newMemberElm.addElement("age");
~~~
#### 7、設置節點文字?
~~~
element.setText("29");
~~~
#### 8、刪除某節點
~~~
//childElm是待刪除的節點,parentElm是其父節點
parentElm.remove(childElm);
~~~
#### 9、添加一個CDATA節點
~~~
Element contentElm = infoElm.addElement("content");
contentElm.addCDATA(diary.getContent());
~~~
PS:注意不能跨層訪問節點。
### 節點對象屬性
#### 1、取得某節點下的某屬性
~~~
Element root=document.getRootElement();????
? ??//屬性名name
Attribute attribute=root.attribute("size");
~~~
#### 2、取得屬性的文字
~~~
??? String text=attribute.getText();
~~~
#### 3、刪除某屬性
~~~
Attribute attribute=root.attribute("size");
root.remove(attribute);
~~~
#### 4、遍歷某節點的所有屬性
~~~
?? Element root=document.getRootElement();????
? for(Iterator it=root.attributeIterator();it.hasNext();){
?????? Attribute attribute = (Attribute) it.next();
?????? String text=attribute.getText();
???????? System.out.println(text);
??? }
~~~
#### 5、設置某節點的屬性和文字
~~~
newMemberElm.addAttribute("name", "sitinspring");
~~~
#### 6、設置屬性的文字
~~~
Attribute attribute=root.attribute("name");
?? attribute.setText("sitinspring");
~~~
### 在指定位置插入節點?
1.得到插入位置的節點列表(list)
2.調用list.add(index,elemnent),由index決定element的插入位置。
Element元素可以通過DocumentHelper對象得到。示例代碼:
~~~
Element aaa = DocumentHelper.createElement("aaa");
aaa.setText("aaa");
List list = root.element("書").elements();
list.add(1, aaa);
//更新document
~~~
### 將文檔寫入XML文件
#### 1、如果文檔是全英文
~~~
XMLWriter writer = new XMLWriter(new FileWriter("output.xml"));
writer.write(document);
writer.close();
~~~
#### 2、如果文檔含有中文
~~~
OutputFormat outputFormat = OutputFormat.createPrettyPrint();
outputFormat.setEncoding("utf-8");
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("src/com/pc/XML8.xml"), outputFormat);
xmlWriter.write(document);
xmlWriter.close();
~~~
PS:出現亂碼的原因是因為輸出字符集不能識別中文,這樣可以通過OutputFormat的setEncoding方法設置為”UTF-8”,然后再使用XMLWriter這種形參的(OutputStream?out,?OutputFormat?format)?構造方構造方法,就能解決亂碼問題了,至于為什么會用createPrettyPrint方法,是因為這樣做輸出的格式更符合人的閱讀習慣。
### 綜合案例
**XML8.xml**
~~~
<?xml version="1.0" encoding="utf-8"?>
<班級 班次="1班" 編號="C1">
<學生 學號="n1" 性別="男" 授課方式="面授" 朋友="n2" 班級編號="C1">
<名字>張三</名字>
<年齡>20</年齡>
<介紹>不錯</介紹>
</學生>
<學生 學號="n2" 性別="女" 授課方式="面授" 朋友="n1 n3" 班級編號="C1">
<名字>李四</名字>
<年齡>18</年齡>
<介紹>很好</介紹>
</學生>
<學生 學號="n3" 性別="男" 授課方式="面授" 朋友="n2" 班級編號="C1">
<名字>王五</名字>
<年齡>22</年齡>
<介紹>非常好</介紹>
</學生>
<學生 性別="男" 班級編號="C1">
<名字>小明</名字>
<年齡>30</年齡>
<介紹>好</介紹>
</學生>
</班級>
~~~
~~~
package com.pc;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
/**
*
* @author Switch
* @function 使用DOM4j解析XML文件
*
*/
public class XML8 {
// 使用DOM4j對XML進行CRUD操作
public static void main(String[] args) throws Exception {
// 1.得到解析器
SAXReader saxReader = new SAXReader();
// 2.指定解析哪個XML文件
Document document = saxReader.read(new File("src/com/pc/XML8.xml"));
// list(document.getRootElement());
// read(document);
// readByXPath(document);
// add(document);
// delete(document);
// updateElement(document);
// updateAttribute(document);
// addByIndex(document, 3);
}
// 更新屬性(修改所有班級編號為C2)
public static void updateAttribute(Document document) throws Exception {
// 得到所有學生
List<Element> students = document.getRootElement().elements("學生");
for (Element e : students) {
// 修改班級編號
e.addAttribute("班級編號", "C2");
}
updateToXML(document);
}
// 更新元素(將所有學生的年齡+3)
public static void updateElement(Document document) throws Exception {
// 得到所有學生
List<Element> students = document.getRootElement().elements("學生");
for (Element e : students) {
// 取出年齡
Element age = e.element("年齡");
age.setText(Integer.parseInt(age.getTextTrim()) + 3 + "");
}
updateToXML(document);
}
// 刪除元素(刪除第一個學生)
public static void delete(Document document) throws Exception {
// 找到元素
Element stu = document.getRootElement().element("學生");
// 刪除
stu.getParent().remove(stu);
// 更新
updateToXML(document);
}
// 添加元素到指定位置
public static void addByIndex(Document document, int index)
throws Exception {
// 創建一個元素
Element newStu = DocumentHelper.createElement("學生");
newStu.setText("小花");
// 得到所有學生的list
List<Element> students = document.getRootElement().elements("學生");
// 按索引添加
students.add(index, newStu);
// 更新
updateToXML(document);
}
// 添加元素(添加一個學生到xml中)
public static void add(Document document) throws Exception {
// 創建一個學生節點對象
Element newStu = DocumentHelper.createElement("學生");
// 給元素添加屬性
newStu.addAttribute("學號", "n4");
Element newStuName = DocumentHelper.createElement("名字");
Element newStuAge = DocumentHelper.createElement("年齡");
Element newStuIntro = DocumentHelper.createElement("介紹");
// 把子元素掛載到學生節點下
newStu.add(newStuName);
newStu.add(newStuAge);
newStu.add(newStuIntro);
// 將學生掛載在根節點下
document.getRootElement().add(newStu);
// 更新
updateToXML(document);
}
private static void updateToXML(Document document)
throws UnsupportedEncodingException, FileNotFoundException,
IOException {
// 更新xml文件
// 直接輸出會出現中文亂碼
OutputFormat outputFormat = OutputFormat.createPrettyPrint();
outputFormat.setEncoding("utf-8");
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream(
"src/com/pc/XML8.xml"), outputFormat);
xmlWriter.write(document);
xmlWriter.close();
}
// xpath技術,跨層讀取某個元素
public static void readByXPath(Document document) throws Exception {
// 取出第一個學生
Element student = (Element) document.selectSingleNode("/班級/學生[1]");
System.out.println("姓名:" + student.elementText("名字") + "\t年齡:"
+ student.elementText("年齡") + "\t介紹:"
+ student.elementText("介紹") + "\t性別:"
+ student.attributeValue("性別"));
}
// 讀取指定的某個元素(讀取第一個學生的信息)
public static void read(Document document) throws Exception {
// 得到根元素
Element root = document.getRootElement();
// root.elements("學生"); 取出root元素下的所有學生元素
// root.element("學生"); 取出root元素下的第一個學生元素
// 取出root元素下的第一個學生元素
Element student = (Element) root.elements("學生").get(0);
System.out.println("姓名:" + student.elementText("名字") + "\t年齡:"
+ student.elementText("年齡") + "\t介紹:"
+ student.elementText("介紹") + "\t性別:"
+ student.attributeValue("性別"));
}
// 遍歷xml文件
public static void list(Element element) {
System.out.println("元素名稱:" + element.getName() + "\t元素內容:"
+ element.getTextTrim());
Iterator<Element> iterator = element.elementIterator();
while (iterator.hasNext()) {
Element e = iterator.next();
// 遞歸
list(e);
}
}
}
~~~