目录
- 为什么选择 dom4j?
- 环境准备:添加依赖
- 核心 API 介绍
- 完整示例:解析 XML 文件
- 准备 XML 文件
- 编写 Java 解析代码
- 代码详解
- 常用操作详解
- 遍历节点
- 读取节点属性和文本内容
- 使用 XPath 快速查询
- 创建和修改 XML
为什么选择 dom4j?
在 Java 中解析 XML 有多种方式,如 SAX、DOM 和 JDOM。dom4j 相比它们有以下优势:

- 性能卓越:
dom4j使用了大量的接口和抽象类,设计上非常灵活,并且底层对性能做了优化,通常比JDOM和标准的DOM更快。 - 功能强大:支持
XPath、XSLT、XML Schema等高级 XML 标准。 - API 简洁易用:API 设计直观,学习曲线相对平缓。
- 社区活跃:被许多知名项目(如 Hibernate、Spring)所使用,文档和社区支持非常丰富。
环境准备:添加依赖
如果你使用的是 Maven,只需在 pom.xml 文件中添加 dom4j 的依赖即可:
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.4</version> <!-- 建议使用较新版本 -->
</dependency>
如果你不使用 Maven,可以从 Maven 中央仓库 下载对应的 JAR 包,并添加到你的项目中。
核心 API 介绍
理解 dom4j 的核心类是上手的关键:
| 类/接口 | 描述 |
|---|---|
Document |
代表整个 XML 文档,它是树结构的根,可以通过 SAXReader 或 DOMReader 创建。 |
Element |
代表 XML 中的一个元素,这是 dom4j 中最重要的接口,几乎所有操作都围绕它展开,元素可以有子元素、属性和文本内容。 |
Attribute |
代表元素的属性。 |
Node |
Element、Attribute、Document 等都实现了 Node 接口,它们都是 XML 树中的一个节点。 |
Branch |
Document 和 Element 都实现了 Branch 接口,表示可以包含其他节点的分支节点。 |
Text |
代表元素或属性的文本内容。 |
SAXReader |
这是解析 XML 文档的核心类,它使用 SAX 解析器将 XML 文档读入内存,并构建 Document 对象。 |
完整示例:解析 XML 文件
这是一个最常见的需求:读取一个 XML 文件,并提取其中的信息。

准备 XML 文件
假设我们有一个名为 books.xml 的文件,内容如下:
books.xml
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book category="children">
<title lang="en">Harry Potter</title>
<author>J.K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="web">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
编写 Java 解析代码
我们将创建一个 Java 类,读取 books.xml,并打印出每本书的信息。
Dom4jParserDemo.java

import org.dom4j.*;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.util.List;
public class Dom4jParserDemo {
public static void main(String[] args) {
// 1. 创建 SAXReader 对象,这个对象是 dom4j 用于解析的核心
SAXReader reader = new SAXReader();
try {
// 2. 读取 XML 文件,获取 Document 对象(整个 XML 文档的树形结构)
// 注意:请确保 books.xml 文件位于项目的根目录下,或提供正确的路径
Document document = reader.read(new File("books.xml"));
// 3. 获取 XML 文档的根元素 <bookstore>
Element rootElement = document.getRootElement();
// 4. 遍历根元素下的所有 <book> 节点
// element.elements("book") 会获取所有直接名为 "book" 的子元素
List<Element> bookList = rootElement.elements("book");
System.out.println("开始解析书籍信息...\n");
for (Element book : bookList) {
// 5. 获取节点的属性,category="children"
String category = book.attributeValue("category");
System.out.println("----- 开始解析一本书 -----");
System.out.println("书籍类别: " + category);
// 6. 获取子节点(如 <title>, <author> 等)的文本内容
// element.element("title") 获取第一个名为 "title" 的子元素
// elementText("title") 是一个便捷方法,直接获取指定子元素的文本内容
String title = book.elementText("title");
String author = book.elementText("author");
String year = book.elementText("year");
String price = book.elementText("price");
System.out.println("书名: " + title);
System.out.println("作者: " + author);
System.out.println("出版年份: " + year);
System.out.println("价格: " + price);
// 7. 获取子节点的属性,lang="en"
// 先获取 <title> 元素,再获取其属性
Element titleElement = book.element("title");
String lang = titleElement.attributeValue("lang");
System.out.println("语言: " + lang);
System.out.println("----- 解析完成 -----\n");
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
代码详解
SAXReader reader = new SAXReader();: 创建解析器。reader.read(new File("books.xml"));: 解析指定的 XML 文件,返回一个Document对象,代表了整个 XML 的内存模型。document.getRootElement();: 获取 XML 的根元素(<bookstore>)。rootElement.elements("book");: 获取根元素下所有名为book的子元素,返回一个List<Element>。book.attributeValue("category");: 获取当前book元素的category属性的值。book.elementText("title");: 这是一个非常方便的方法,它会查找当前元素下第一个名为title的子元素,并直接返回其文本内容,避免了先获取Element再获取Text的繁琐步骤。book.element("title").attributeValue("lang");: 如果要获取子元素的属性,需要先通过element()方法获取该子元素,然后调用其attributeValue()方法。
常用操作详解
遍历节点(递归方式)
上面的示例是遍历已知子节点,如果需要遍历一个元素下的所有节点(包括未知名称的节点),可以使用递归。
// 这是一个递归遍历所有节点的方法
public void traverse(Element element) {
// 1. 处理当前节点
System.out.println("节点名称: " + element.getName());
if (!element.isTextOnly()) {
System.out.println("节点路径: " + element.getPath());
}
List<Attribute> attributes = element.attributes();
for (Attribute attr : attributes) {
System.out.println(" - 属性: " + attr.getName() + " = " + attr.getValue());
}
// 2. 递归处理子节点
for (Iterator<Node> it = element.nodeIterator(); it.hasNext(); ) {
Node node = it.next();
if (node instanceof Element) {
traverse((Element) node); // 递归
} else if (node.getNodeType() == Node.TEXT_NODE) {
// 处理文本节点,通常需要去除空白文本
Text textNode = (Text) node;
String text = textNode.getText().trim();
if (!text.isEmpty()) {
System.out.println(" - 文本内容: " + text);
}
}
}
}
使用 XPath 快速查询
dom4j 对 XPath 提供了完美的支持。XPath 是一种在 XML 文档中查找信息的语言,比手动遍历节点要简洁和高效得多。
示例:
// 假设我们已经有了 document 和 rootElement
// 1. 获取所有 <book> 节点
List<Node> books = document.selectNodes("//book");
// 2. 获取第一本书的 <title> 节点
Node firstTitle = document.selectSingleNode("//book[1]/title");
System.out.println("第一本书的标题: " + firstTitle.getText());
// 3. 获取所有价格大于 30 的书的作者
List<Node> authors = document.selectNodes("//book[price > 30]/author");
System.out.println("\n价格大于 30 的书的作者:");
for (Node author : authors) {
System.out.println(author.getText());
}
// 4. 获取 lang 属性为 "en" 的所有标题
List<Node> enTitles = document.selectNodes("//book/title[@lang='en']");
System.out.println("\n语言为 'en' 的所有标题:");
for (Node title : enTitles) {
System.out.println(title.getText());
}
创建和修改 XML
dom4j 不仅可以读取,还可以创建和修改 XML。
示例:创建一个新的 XML 文件
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import java.io.FileWriter;
import java.io.IOException;
public class CreateXmlExample {
public static void main(String[] args) throws IOException {
// 1. 创建一个 Document 对象
Document document = DocumentHelper.createDocument();
// 2. 添加根元素 <students>
Element root = document.addElement("students");
// 3. 在根元素下添加子元素 <student>
Element student1 = root.addElement("student");
student1.addAttribute("id", "001");
// 4. 在 <student> 下添加子元素和文本
student1.addElement("name").addText("张三");
student1.addElement("age").addText("20");
// 5. 同样方式添加第二个学生
Element student2 = root.addElement("student").addAttribute("id", "002");
student2.addElement("name").addText("李四");
student2.addElement("age").addText("21");
// 6. 设置格式化输出
OutputFormat format = OutputFormat.createPrettyPrint();
// format.setEncoding("GBK"); // 如果需要指定编码
// 7. 创建 XMLWriter 并写入文件
XMLWriter writer = new XMLWriter(new FileWriter("new_students.xml"), format);
writer.write(document);
writer.close();
System.out.println("XML 文件创建成功: new_students.xml");
}
}
dom4j 是 Java 处理 XML 的利器,掌握它的关键在于:
- 理解树形模型:将 XML 看作一棵由
Document、Element、Attribute、Text等节点组成的树。 - 熟练使用核心 API:
SAXReader用于读取和解析。Document代表整个文档。Element代表元素,是操作的核心。attributeValue()和elementText()是最常用的获取属性和文本内容的方法。
- 拥抱 XPath:对于复杂的查询,
XPath能让你用非常简洁的定位符快速找到目标节点,极大提升开发效率。
通过以上学习和实践,你就可以在 Java 项目中灵活地使用 dom4j 来解析、创建和操作 XML 数据了。
