# 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);
}
}
}
~~~