dom4j 是一个功能强大、性能优异且易于使用的 Java XML 框架,它广泛应用于各种项目中,它的核心特点是:

- 支持 XPath: 可以非常方便地使用 XPath 表达式来查找节点。
- 支持 SAX, DOM, and JAXP: 提供了多种解析方式。
- 性能优异: 通常比标准的 JDK
org.w3c.dom更快。 - 易于使用: API 设计非常直观。
第一步:添加 dom4j 依赖
在使用 dom4j 之前,你需要确保你的项目中已经添加了它的依赖,如果你使用 Maven,请在 pom.xml 文件中添加以下依赖:
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.4</version> <!-- 建议使用较新版本 -->
</dependency>
注意: dom4j 的运行依赖于另一个 XML 解析库,通常是 jaxen,Maven 在引入 dom4j 时通常会自动将其作为传递依赖(transitive dependency)一并下载,所以你通常不需要手动添加。
第二步:准备一个示例 XML 文件
为了演示,我们创建一个名为 students.xml 的文件,内容如下:
students.xml

<?xml version="1.0" encoding="UTF-8"?>
<class name="计算机科学1班">
<student id="001">
<name>张三</name>
<age>20</age>
<gender>男</gender>
<courses>
<course name="Java编程"/>
<course name="数据结构"/>
</courses>
</student>
<student id="002">
<name>李四</name>
<age>21</age>
<gender>女</gender>
<courses>
<course name="算法设计"/>
<course name="计算机网络"/>
</courses>
</student>
</class>
第三步:核心 API 简介
在开始解析之前,我们先了解几个核心的 dom4j 类:
SAXReader: 这是dom4j的核心解析器类,用于将 XML 文件读取并解析成一个Document对象。Document: 代表整个 XML 文档的顶层对象,类似于一个树结构的根。Element: 代表 XML 中的一个元素(节点),是Document和Branch的子接口,我们大部分操作都是基于Element。Attribute: 代表元素的属性。Node: 是所有节点(Element,Attribute,Document等)的公共父接口,提供了一些通用的方法。XPath: 用于在 XML 文档中查找信息的语言。dom4j对 XPath 提供了非常好的支持。
第四步:代码实现(多种读取方式)
下面我们通过完整的 Java 代码来演示如何读取 students.xml 文件。
读取根元素及其子元素(基础遍历)
这是最基本的方式,我们从根元素开始,逐层遍历子元素。
import org.dom4j.*;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.util.List;
public class Dom4jBasicReader {
public static void main(String[] args) {
try {
// 1. 创建 SAXReader 对象,这是 dom4j 的解析器
SAXReader reader = new SAXReader();
// 2. 读取 XML 文件,获取 Document 对象
// 注意:文件路径要正确,这里假设 students.xml 在项目根目录下
Document document = reader.read(new File("students.xml"));
// 3. 获取根元素
Element rootElement = document.getRootElement();
System.out.println("根元素名称: " + rootElement.getName());
System.out.println("根元素属性 (name): " + rootElement.attributeValue("name"));
System.out.println("---------------------------------");
// 4. 遍历根元素下的所有子元素(即所有的 <student> 标签)
List<Element> studentList = rootElement.elements("student");
for (Element student : studentList) {
// 5. 获取元素的属性
String id = student.attributeValue("id");
System.out.println("学生ID: " + id);
// 6. 获取元素下的子元素文本内容
String name = student.elementText("name");
String age = student.elementText("age");
String gender = student.elementText("gender");
System.out.println(" 姓名: " + name);
System.out.println(" 年龄: " + age);
System.out.println(" 性别: " + gender);
// 7. 遍历嵌套的子元素(如 <courses>)
Element coursesElement = student.element("courses");
if (coursesElement != null) {
List<Element> courseList = coursesElement.elements("course");
System.out.print(" 选修课程: ");
for (Element course : courseList) {
// 获取元素的属性
System.out.print(course.attributeValue("name") + " ");
}
System.out.println();
}
System.out.println("---------------------------------");
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
输出结果:

根元素名称: class
根元素属性 (name): 计算机科学1班
---------------------------------
学生ID: 001
姓名: 张三
年龄: 20
性别: 男
选修课程: Java编程 数据结构
---------------------------------
学生ID: 002
姓名: 李四
年龄: 21
性别: 女
选修课程: 算法设计 计算机网络
---------------------------------
使用 XPath 快速定位节点
当 XML 结构复杂时,逐层遍历非常繁琐。dom4j 强大的 XPath 支持可以让我们直接“跳”到目标节点。
import org.dom4j.*;
import org.dom4j.io.SAXReader;
import java.util.List;
public class Dom4jXPathReader {
public static void main(String[] args) {
try {
SAXReader reader = new SAXReader();
Document document = reader.read(new File("students.xml"));
// XPath 示例
// 1. 获取所有名为 'student' 的节点
// // 表示从任意位置开始
List<Node> allStudents = document.selectNodes("//student");
System.out.println("所有学生数量: " + allStudents.size());
// 2. 获取第一个学生的姓名
// / 表示从根开始
String firstName = document.selectSingleNode("/class/student[1]/name").getText();
System.out.println("第一个学生姓名: " + firstName);
// 3. 获取ID为 '002' 的学生的姓名
// @ 表示属性
Node secondStudentNode = document.selectSingleNode("//student[@id='002']");
if (secondStudentNode != null) {
String secondName = secondStudentNode.selectSingleNode("name").getText();
System.out.println("ID为002的学生姓名: " + secondName);
}
// 4. 获取所有学生的姓名
List<Node> allNames = document.selectNodes("//student/name");
System.out.println("\n所有学生姓名列表:");
for (Node nameNode : allNames) {
System.out.println(nameNode.getText());
}
// 5. 获取所有课程名称
List<Node> allCourseNames = document.selectNodes("//course/@name");
System.out.println("\n所有课程名称列表:");
for (Node courseNameNode : allCourseNames) {
// 对于属性节点,使用 getStringValue() 或 getText()
System.out.println(courseNameNode.getStringValue());
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
输出结果:
所有学生数量: 2
第一个学生姓名: 张三
ID为002的学生姓名: 李四
所有学生姓名列表:
张三
李四
所有课程名称列表:
Java编程
数据结构
算法设计
计算机网络
第五步:处理 XML 声明和编码
dom4j 在读取 XML 时,会自动处理 XML 声明(<?xml version="1.0" encoding="UTF-8"?>)中声明的编码,你只需要确保在读取文件时,你的 Java 代码环境(IDE、文件系统)的编码与 XML 文件声明的编码一致即可。
如果需要手动获取文档的编码信息,可以通过 Document 对象:
// 在读取完 document 后
String encoding = document.getXMLEncoding();
System.out.println("XML 文档编码: " + encoding); // 输出: UTF-8
总结与最佳实践
-
选择合适的方法:
- XML 结构简单或需要遍历所有节点,使用 基础遍历。
- XML 结构复杂或只需要提取特定信息,XPath 是首选,它更简洁、更高效。
-
异常处理:
SAXReader.read()方法会抛出DocumentException,务必进行try-catch处理,以应对文件不存在、格式错误等情况。 -
空指针检查: 使用
element("name")方法时,如果指定的子元素不存在,它会返回null,在调用.getText()或其他方法前,最好进行空值检查,避免NullPointerException。elementText("name")方法相对安全,如果元素不存在,它会返回null而不是抛出异常。 -
资源管理:
SAXReader本身不涉及需要手动关闭的流(它内部会处理),但如果你使用的是InputStream或Reader来构建Document,请确保在使用后关闭它们。
通过以上步骤和示例,你应该已经掌握了使用 dom4j 读取 XML 文件的基本方法。dom4j 是一个非常强大的工具,熟练掌握它将大大提高你处理 XML 数据的效率。
