杰瑞科技汇

dom4j如何高效解析XML?

目录

  1. 准备工作:添加 dom4j 依赖
  2. 核心 API 介绍
  3. 示例 XML 文件
  4. 解析步骤详解
    • 读取 XML 文件
    • 获取根元素
    • 遍历子元素
    • 获取元素属性和文本内容
    • 使用 XPath 快速查询
  5. 完整代码示例
  6. 写入 XML 文件

准备工作:添加 dom4j 依赖

你需要在你的项目中添加 dom4j 的依赖,如果你使用的是 Maven,可以在 pom.xml 文件中添加如下依赖:

dom4j如何高效解析XML?-图1
(图片来源网络,侵删)
<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: 一个工具类,用于创建 DocumentElement 等对象。
  • SAXReader: 这是 dom4j 中最常用的解析器,它使用 SAX(Simple API for XML)方式来读取 XML 文件,并将其构建成内存中的 Document 对象树。

示例 XML 文件

我们创建一个名为 books.xml 的文件,作为我们解析的目标。

dom4j如何高效解析XML?-图2
(图片来源网络,侵删)
<?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 遍历所有直接子元素

dom4j如何高效解析XML?-图3
(图片来源网络,侵删)
// 遍 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 属性为 webbook 元素。
  • //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 的使用!

分享:
扫描分享到社交APP
上一篇
下一篇