准备工作:添加 dom4j 依赖
你需要在你的 Java 项目中添加 dom4j 的依赖,如果你使用 Maven,这是最简单的方式。

Maven (pom.xml)
在你的 pom.xml 文件中添加以下依赖:
<dependencies>
<!-- dom4j 核心库 -->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.4</version> <!-- 建议使用较新版本 -->
</dependency>
<!-- dom4j 依赖的 XPath 实现 -->
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.2.0</version>
</dependency>
</dependencies>
如果你不使用 Maven,可以从 Maven 中央仓库 下载 dom4j-2.1.4.jar 和 jaxen-1.2.0.jar,然后手动添加到你的项目的 classpath 中。
示例 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>
<book category="cooking">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
</bookstore>
核心概念和 API
在开始解析之前,了解几个核心类和接口很重要:
SAXReader: 这是dom4j的核心解析器类,它的read()方法可以接收一个File、URL或InputStream对象,并返回一个Document对象。Document: 代表整个 XML 文档的树形结构,它包含了根元素。Element: 代表 XML 文档中的一个元素(节点),大部分操作都是围绕Element进行的。Attribute: 代表元素的属性。Node:Element、Attribute、Text等的父接口,提供了通用的节点操作方法,如getNodeName()、getText()等。DocumentHelper: 一个工具类,用于创建Document、Element等对象。
完整解析示例
下面是一个完整的 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) {
try {
// 1. 创建 SAXReader 实例
SAXReader reader = new SAXReader();
// 2. 指定 XML 文件的路径
File xmlFile = new File("books.xml");
// 3. 读取 XML 文件,获取 Document 对象
// Document 对象代表了整个 XML 文档的树形结构
Document document = reader.read(xmlFile);
// 4. 获取根元素
// 根元素是 <bookstore>
Element rootElement = document.getRootElement();
// 5. 遍历根元素下的所有子元素
// 使用 elementIterator("book") 可以只遍历名为 "book" 的子元素
// 或者使用 elements("book") 获取所有 "book" 元素的列表
List<Element> bookList = rootElement.elements("book");
System.out.println("共找到 " + bookList.size() + " 本书:\n");
for (Element book : bookList) {
System.out.println("----- 开始解析一本书 -----");
// 6. 获取元素的属性
// <book category="children"> 中的 "category"
String category = book.attributeValue("category");
System.out.println("类别: " + category);
// 7. 获取子元素的文本内容
// <title>Harry Potter</title> 中的 "Harry Potter"
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);
// 8. 获取带有属性的子元素的属性值
// <title lang="en"> 中的 "lang"
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(xmlFile);: 解析 XML 文件,返回一个Document对象,这是整个解析过程的入口。document.getRootElement();: 获取 XML 的根节点,这里是<bookstore>。rootElement.elements("book"): 获取根节点下所有名为book的子元素,返回一个List<Element>,这是遍历 XML 结构最常用的方法之一。book.attributeValue("category"): 获取当前book元素的category属性的值。book.elementText("title"): 获取当前book元素下名为title的子元素的文本内容,这是一个非常便捷的方法。book.element("title").attributeValue("lang"): 先获取title元素,然后调用其attributeValue方法来获取lang属性的值。
使用 XPath 进行更强大的查询
dom4j 对 XPath 提供了非常好的支持,XPath 是一种在 XML 文档中查找信息的语言,比逐层遍历更简洁、更强大。
如何使用 XPath?
通过 document.selectNodes() 或 element.selectNodes() 可以执行 XPath 表达式,返回一个 List<Node>,通过 document.selectSingleNode() 或 element.selectSingleNode() 可以返回单个 Node。
示例:使用 XPath 查询
import org.dom4j.*;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.util.List;
public class Dom4jXPathDemo {
public static void main(String[] args) {
try {
SAXReader reader = new SAXReader();
Document document = reader.read(new File("books.xml"));
// XPath 示例 1: 获取所有书籍的标题
System.out.println("--- 所有书籍的标题 ---");
List<Node> titleNodes = document.selectNodes("//book/title");
for (Node node : titleNodes) {
Element titleElement = (Element) node;
System.out.println(titleElement.getText());
}
// XPath 示例 2: 获取所有价格大于 30 的书籍
System.out.println("\n--- 价格大于 30 的书籍 ---");
List<Node> expensiveBooks = document.selectNodes("//book[price > 30]");
for (Node node : expensiveBooks) {
Element bookElement = (Element) node;
System.out.println("书名: " + bookElement.elementText("title") +
", 价格: " + bookElement.elementText("price"));
}
// XPath 示例 3: 获取第一本书的语言属性
System.out.println("\n--- 第一本书的语言属性 ---");
Node firstBookLangNode = document.selectSingleNode("//book[1]/title/@lang");
if (firstBookLangNode != null) {
Attribute langAttribute = (Attribute) firstBookLangNode;
System.out.println("语言: " + langAttribute.getValue());
}
// XPath 示例 4: 获取作者为 'J.K. Rowling' 的书籍
System.out.println("\n--- 作者为 'J.K. Rowling' 的书籍 ---");
List<Node> booksByAuthor = document.selectNodes("//book[author='J.K. Rowling']");
for (Node node : booksByAuthor) {
Element bookElement = (Element) node;
System.out.println("书名: " + bookElement.elementText("title"));
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
XPath 表达式解释:
//book/title: 选择所有名为book的元素下的所有名为title的元素,无论它们在文档中的位置多深。//book[price > 30]: 使用谓语[price > 30]筛选price子元素的文本值大于 30 的book元素。//book[1]/title/@lang:book[1]选择第一个book元素。/title选择其子元素title。/@lang选择title元素的lang属性。//book[author='J.K. Rowling']: 使用谓语[author='J.K. Rowling']筛选author子元素的文本值等于 'J.K. Rowling' 的book元素。
修改 XML 文件
dom4j 不仅可以解析 XML,还可以创建、修改和写入 XML。
示例:修改 XML 并保存
import org.dom4j.*;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import java.io.File;
import java.io.FileOutputStream;
public class Dom4jModifyDemo {
public static void main(String[] args) {
try {
SAXReader reader = new SAXReader();
Document document = reader.read(new File("books.xml"));
// 1. 修改现有内容
// 找到第一本书的价格并修改
Element firstBook = (Element) document.selectSingleNode("//book[1]");
firstBook.element("price").setText("19.99");
// 2. 添加新元素
// 在第一本书中添加一个 <publisher> 元素
Element publisher = DocumentHelper.createElement("publisher");
publisher.setText("Bloomsbury Publishing");
firstBook.add(publisher);
// 3. 添加新属性
// 给第一本书的 title 元素添加一个新属性 id="001"
Element firstBookTitle = firstBook.element("title");
firstBookTitle.addAttribute("id", "001");
// 4. 删除元素
// 删除最后一本书
Element lastBook = (Element) document.selectSingleNode("//book[last()]");
Element parent = lastBook.getParent();
parent.remove(lastBook);
// 5. 将修改后的 Document 写入文件
// 使用 OutputFormat 可以控制输出格式,如缩进和编码
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8"); // 设置编码
XMLWriter writer = new XMLWriter(new FileOutputStream(new File("books_modified.xml")), format);
writer.write(document);
writer.close();
System.out.println("XML 文件修改成功,已保存为 books_modified.xml");
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行后,会生成一个 books_modified.xml 文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book category="children">lang="en" id="001">Harry Potter</title>
<author>J.K. Rowling</author>
<year>2005</year>
<price>19.99</price>
<publisher>Bloomsbury Publishing</publisher>
</book>
<book category="web">lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
| 功能 | 核心方法/代码 | 说明 |
|---|---|---|
| 解析 | SAXReader reader = new SAXReader();Document doc = reader.read(file); |
创建解析器并读取 XML 文件,得到 Document 对象。 |
| 获取根元素 | Element root = doc.getRootElement(); |
获取 XML 的顶层节点。 |
| 遍历子元素 | List<Element> list = root.elements("book"); |
获取指定名称的直接子元素列表。 |
| 获取属性 | String attrValue = element.attributeValue("name"); |
获取元素的属性值。 |
| 获取文本 | String text = element.elementText("title"); |
获取指定子元素的文本内容。 |
| XPath 查询 | List<Node> nodes = doc.selectNodes("//book/price"); |
使用 XPath 表达式高效查询节点。 |
| 修改元素 | element.setText("new text"); |
修改元素的文本内容。 |
| 添加元素 | parentElement.addElement("newChild"); |
添加一个新的子元素。 |
| 添加属性 | element.addAttribute("id", "123"); |
为元素添加一个新属性。 |
| 删除元素 | parent.remove(child); |
从父节点中移除一个子节点。 |
| 写入文件 | XMLWriter writer = new XMLWriter(outputStream, format);writer.write(document); |
将 Document 对象写出到文件或流。 |
dom4j 是一个非常灵活和强大的工具,无论是简单的数据提取还是复杂的 XML 文档操作,它都能胜任,希望这份详细的教程能帮助你掌握它!
