目录
- 准备工作:添加 dom4j 依赖
- 核心 API 介绍
- 示例 XML 文件
- 解析步骤详解
- 读取 XML 文件
- 获取根元素
- 遍历子元素
- 获取元素属性和文本内容
- 使用 XPath 快速查询
- 完整代码示例
- 写入 XML 文件
准备工作:添加 dom4j 依赖
你需要在你的项目中添加 dom4j 的依赖,如果你使用的是 Maven,可以在 pom.xml 文件中添加如下依赖:

<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.4</version> <!-- 建议使用较新版本 -->
</dependency>
如果你使用 Gradle,在 build.gradle 文件中添加:
implementation 'org.dom4j:dom4j:2.1.4'
注意:dom4j 依赖于另一个 XML 解析库,通常是 jaxen,如果你使用 Maven 或 Gradle,它会自动帮你管理这些依赖。
核心 API 介绍
在开始编码前,先了解几个核心的 dom4j 类和接口:
Document: 代表整个 XML 文档在内存中的树形结构。Element: 代表 XML 文档中的一个元素(标签),是构建 XML 树的基本单元。Attribute: 代表元素的属性。Node: 是所有节点(Element,Attribute,Document等)的基接口。DocumentHelper: 一个工具类,用于创建Document、Element等对象。SAXReader: 这是dom4j中最常用的解析器,它使用 SAX(Simple API for XML)方式来读取 XML 文件,并将其构建成内存中的Document对象树。
示例 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>
<book category="cooking">
<title lang="zh">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
</bookstore>
解析步骤详解
1 读取 XML 文件
使用 SAXReader 来读取 XML 文件并生成 Document 对象。
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
// 创建 SAXReader 实例
SAXReader reader = new SAXReader();
try {
// 读取 XML 文件,获取 Document 对象
// 注意:文件路径需要正确,可以是绝对路径或相对于 classpath 的路径
Document document = reader.read(new File("src/main/resources/books.xml"));
// 或者从输入流读取
// Document document = reader.read(inputStream);
// 后续操作基于 document 对象...
} catch (DocumentException e) {
e.printStackTrace();
}
2 获取根元素
XML 文档有且只有一个根元素。
// 获取根元素
Element rootElement = document.getRootElement();
System.out.println("根元素是: " + rootElement.getName()); // 输出: bookstore
3 遍历子元素
dom4j 提供了多种遍历方式。
使用 elementIterator 遍历所有直接子元素

// 遍 bookstore 的所有直接子元素 (即 <book> 元素)
Iterator<Element> bookIterator = rootElement.elementIterator("book");
while (bookIterator.hasNext()) {
Element bookElement = bookIterator.next();
System.out.println("\n找到一本书: " + bookElement.attributeValue("category"));
}
使用 elements() 获取所有指定名称的子元素列表
// 获取所有名为 "book" 的子元素
List<Element> bookList = rootElement.elements("book");
for (Element book : bookList) {
System.out.println("\n找到一本书: " + book.attributeValue("category"));
}
递归遍历所有后代元素
如果你想遍历整个 XML 树的每一个元素,可以使用 elementIterator() 不带参数的版本。
// 递归遍历所有后代元素
Iterator<Element> allElementIterator = rootElement.elementIterator();
while (allElementIterator.hasNext()) {
Element element = allElementIterator.next();
System.out.println("元素名: " + element.getName());
}
4 获取元素属性和文本内容
element.attributeValue("属性名"): 获取指定属性的值。element.elementText("子元素名"): 获取指定子元素的文本内容,这是最常用的方法之一。element.getText(): 获取当前元素的文本内容。
// 假设我们正在遍历一个 <book> 元素
Element bookElement = rootElement.element("book");
// 获取 category 属性
String category = bookElement.attributeValue("category");
System.out.println("类别: " + category);
// 获取 <title> 子元素的文本
String title = bookElement.elementText("title");
System.out.println("标题: " + title);
// 获取 <author> 子元素的文本
String author = bookElement.elementText("author");
System.out.println("作者: " + author);
// 获取 <price> 子元素的文本并转为 Double
String priceStr = bookElement.elementText("price");
double price = Double.parseDouble(priceStr);
System.out.println("价格: " + price);
5 使用 XPath 快速查询
XPath 是在 XML 文档中查找信息的强大语言。dom4j 对 XPath 提供了非常好的支持。
// 导入 XPath 相关类
import org.dom4j.XPath;
// 创建 XPath 对象
// XPath xpath = document.createXPath("//book[price<30]");
// 或者使用更简洁的静态方法
List<Node> cheapBooks = document.selectNodes("//book[price < 30]");
System.out.println("\n使用 XPath 查找价格低于 30 的书:");
for (Node node : cheapBooks) {
Element book = (Element) node;
System.out.println(" - " + book.elementText("title") + " (价格: " + book.elementText("price") + ")");
}
// 查找第一个 category 为 'children' 的书的标题
String firstChildrenBookTitle = document.valueOf("//book[@category='children']/title");
System.out.println("\n第一本儿童书的标题是: " + firstChildrenBookTitle);
XPath 常用表达式:
//book: 选择所有名为book的元素(无论层级多深)。/bookstore/book: 选择bookstore的直接子元素book。//book[@category='web']: 选择所有category属性为web的book元素。//book/title: 选择所有book元素下的title元素。//book[price<30]: 选择所有price子元素值小于 30 的book元素。//book/title/text(): 选择所有title元素的文本内容。
完整代码示例
下面是一个完整的 Java 类,演示了上述所有解析操作。
import org.dom4j.*;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.util.Iterator;
import java.util.List;
public class Dom4jParser {
public static void main(String[] args) {
// 1. 创建 SAXReader 对象
SAXReader reader = new SAXReader();
try {
// 2. 读取 XML 文件,获取 Document 对象
// 请确保 "books.xml" 文件在你的项目根目录或指定路径下
Document document = reader.read(new File("books.xml"));
// 3. 获取根元素
Element rootElement = document.getRootElement();
System.out.println("根元素: " + rootElement.getName());
// 4. 遍历所有 <book> 元素
System.out.println("\n--- 遍历所有书籍 ---");
List<Element> books = rootElement.elements("book");
for (Element book : books) {
parseBookElement(book);
}
// 5. 使用 XPath 进行高级查询
System.out.println("\n--- 使用 XPath 查询 ---");
// 5.1 查找所有价格低于 30 的书
List<Node> cheapBooks = document.selectNodes("//book[price < 30]");
System.out.println("价格低于 30 的书籍:");
for (Node node : cheapBooks) {
Element book = (Element) node;
System.out.println(" - " + book.elementText("title") + " (价格: " + book.elementText("price") + ")");
}
// 5.2 查找第一本类别为 'children' 的书的标题
String firstChildrenBookTitle = document.valueOf("//book[@category='children']/title");
System.out.println("第一本儿童书的标题是: " + firstChildrenBookTitle);
} catch (DocumentException e) {
e.printStackTrace();
}
}
/**
* 解析单个 <book> 元素的辅助方法
* @param bookElement <book> 元素
*/
private static void parseBookElement(Element bookElement) {
String category = bookElement.attributeValue("category");
String title = bookElement.elementText("title");
String author = bookElement.elementText("author");
String year = bookElement.elementText("year");
String price = bookElement.elementText("price");
System.out.println(" 类别: " + category);
System.out.println(" 标题: " + title);
System.out.println(" 作者: " + author);
System.out.println(" 年份: " + year);
System.out.println(" 价格: " + price);
System.out.println("---------------------------------");
}
}
写入 XML 文件
dom4j 不仅可以读取,还可以创建和写入 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 Dom4jWriter {
public static void main(String[] args) throws IOException {
// 1. 创建一个 Document 对象
Document document = DocumentHelper.createDocument();
// 2. 添加根元素
Element rootElement = document.addElement("root");
// 3. 添加子元素和属性
Element userElement = rootElement.addElement("user");
userElement.addAttribute("id", "001");
userElement.addElement("name").addText("张三");
userElement.addElement("email").addText("zhangsan@example.com");
Element userElement2 = rootElement.addElement("user");
userElement2.addAttribute("id", "002");
userElement2.addElement("name").addText("李四");
userElement2.addElement("email").addText("lisi@example.com");
// 4. 设置输出格式(美化输出)
OutputFormat format = OutputFormat.createPrettyPrint();
// 设置编码
format.setEncoding("UTF-8");
// 5. 创建 XMLWriter 并写入文件
XMLWriter writer = new XMLWriter(new FileWriter("users.xml"), format);
writer.write(document);
writer.close();
System.out.println("XML 文件生成成功: users.xml");
}
}
运行后,会生成一个 users.xml 文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<user id="001">
<name>张三</name>
<email>zhangsan@example.com</email>
</user>
<user id="002">
<name>李四</name>
<email>lisi@example.com</email>
</user>
</root>
| 特性 | 描述 |
|---|---|
| 优点 | 功能强大:支持 XPath、XSLT 等高级特性。 性能优越:底层使用 SAX 解析,内存占用相对较低。 API 友好:API 设计直观,易于使用。 灵活:既可以读取,也可以创建和修改 XML。 |
| 缺点 | 不适合超大文件:虽然使用 SAX 解析,但最终会构建 DOM 树在内存中,对于特别大的 XML 文件(如数 GB),内存消耗依然巨大,这种情况下,应考虑使用 StAX(Streaming API for XML)。 |
| 适用场景 | 中小型 XML 文件的解析、生成、查询和修改,是企业级 Java 应用中处理 XML 的首选库之一。 |
希望这份详细的教程能帮助你掌握 dom4j 的使用!
