杰瑞科技汇

dom4j如何高效读取XML文件?

dom4j 是一个非常流行、功能强大且性能优异的 Java XML 处理框架,它使用的是 DOM(文档对象模型)的思想,将整个 XML 文件读入内存,形成一个树形结构,方便我们遍历和操作。

dom4j如何高效读取XML文件?-图1
(图片来源网络,侵删)

准备工作:添加 dom4j 依赖

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

Maven (pom.xml)

在你的 pom.xml 文件中添加以下依赖:

<dependency>
    <groupId>org.dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>2.1.4</version> <!-- 建议使用较新版本 -->
</dependency>

如果你不使用 Maven,可以从 Maven 中央仓库 下载 JAR 文件,并将其添加到你的项目的类路径中。


示例 XML 文件

为了演示,我们创建一个名为 books.xml 的文件。

dom4j如何高效读取XML文件?-图2
(图片来源网络,侵删)

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>

核心概念

在开始编码前,了解 dom4j 的几个核心接口和类非常重要:

  • Document: 代表整个 XML 文档,它是 XML 树的根节点。
  • Element: 代表 XML 中的一个元素(标签),如 <bookstore>, <book>,它是 Node 的主要子接口。
  • Attribute: 代表元素的属性,如 category="children"
  • Node: dom4j 中所有节点的基接口,包括 Element, Attribute, Document 等。
  • Element 的方法:
    • element(String name): 获取指定名称的第一个子元素。
    • elements(): 获取所有子元素的列表。
    • elements(String name): 获取所有指定名称的子元素列表。
    • attribute(String name): 获取指定名称的属性。
    • attributeValue(String name): 获取指定名称属性的值(常用)。
    • getText(): 获取元素的文本内容。
    • getTextTrim(): 获取并去除文本内容两端的空白字符(常用)。

读取 XML 的完整代码示例

下面是一个完整的 Java 程序,它读取 books.xml 文件,并以不同方式遍历和打印其中的数据。

import org.dom4j.*;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.util.List;
public class Dom4jReaderDemo {
    public static void main(String[] args) {
        try {
            // 1. 创建 SAXReader 对象,它是读取 XML 的核心工具
            SAXReader reader = new SAXReader();
            // 2. 加载 XML 文件,获取 Document 对象
            //    请确保 books.xml 文件位于项目根目录下,或提供正确的路径
            Document document = reader.read(new File("books.xml"));
            // 3. 获取 XML 文档的根元素
            Element rootElement = document.getRootElement();
            System.out.println("根元素是: " + rootElement.getName());
            System.out.println("\n--- 方式一:遍历所有 book 元素 ---");
            // 4. 获取根元素下所有名为 "book" 的子元素列表
            List<Element> bookList = rootElement.elements("book");
            for (Element book : bookList) {
                // 5. 获取元素的属性
                String category = book.attributeValue("category");
                System.out.println("书籍类别: " + category);
                // 6. 获取子元素及其文本内容
                String title = book.element("title").getTextTrim();
                String author = book.element("author").getTextTrim();
                String year = book.element("year").getTextTrim();
                String price = book.element("price").getTextTrim();
                System.out.println("  - 书名: " + title);
                System.out.println("  - 作者: " + author);
                System.out.println("  - 年份: " + year);
                System.out.println("  - 价格: " + price);
                System.out.println("----------------------------------");
            }
            System.out.println("\n--- 方式二:使用迭代器深度遍历所有节点 ---");
            // 7. 使用迭代器遍历所有节点,可以处理更复杂的结构
            Iterator<Node> iterator = document.nodeIterator();
            while (iterator.hasNext()) {
                Node node = iterator.next();
                // 只处理元素节点
                if (node instanceof Element) {
                    Element element = (Element) node;
                    System.out.println("当前节点名称: " + element.getName());
                    // 递归处理子节点
                    printChildNodes(element, 1);
                }
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
    /**
     * 递归打印所有子节点
     * @param element 父元素
     * @param level 缩进层级,用于格式化输出
     */
    private static void printChildNodes(Element element, int level) {
        String indent = "  ".repeat(level); // Java 11+ 的 repeat 方法
        List<Element> children = element.elements();
        if (children.isEmpty()) {
            // 如果是叶子节点,打印其文本内容
            System.out.println(indent + "└── 文本内容: " + element.getTextTrim());
        } else {
            for (Element child : children) {
                System.out.println(indent + "├── " + child.getName());
                printChildNodes(child, level + 1);
            }
        }
    }
}

代码解释:

  1. SAXReader reader = new SAXReader(); 创建 SAXReader 实例,这是解析 XML 的入口。

    dom4j如何高效读取XML文件?-图3
    (图片来源网络,侵删)
  2. reader.read(new File("books.xml")); read() 方法会解析指定的 XML 文件,并返回一个 Document 对象,代表整个 XML 文档树。

  3. document.getRootElement();Document 对象中获取根元素,在我们的例子中就是 <bookstore>

  4. rootElement.elements("book"); 获取根元素下所有名为 book 的子元素,返回一个 List<Element>

  5. book.attributeValue("category"); 直接获取 book 元素的 category 属性的值。

  6. book.element("title").getTextTrim(); 获取 book 元素下的第一个 title 子元素,并调用 getTextTrim() 获取其文本内容(getText() 也会获取,但 getTextTrim() 会去掉首尾多余的空格和换行符,更常用)。

  7. 迭代器遍历 这种方式更通用,不依赖于元素名称。document.nodeIterator() 获取文档中所有节点的迭代器,通过 instanceof 判断节点类型,可以分别处理元素、属性、文本等不同类型的节点,递归调用 printChildNodes 可以实现深度优先遍历。


处理更复杂的情况

1 处理命名空间

XML 文件使用了命名空间,读取方式会稍有不同。

books_with_ns.xml

<bookstore xmlns="http://www.example.com/books">
    <book category="children">
        <title lang="en">Harry Potter</title>
        <author>J.K. Rowling</author>
    </book>
</bookstore>

处理代码:

// ... 前面的代码相同
Document document = reader.read(new File("books_with_ns.xml"));
// 定义命名空间
Namespace ns = new Namespace("ns", "http://www.example.com/books");
// 获取根元素时需要指定命名空间
Element rootElement = document.getRootElement(ns);
System.out.println("根元素是: " + rootElement.getName());
// 获取子元素时也需要指定命名空间
List<Element> bookList = rootElement.elements(new QName("book", ns));
// ... 后续处理相同

2 使用 XPath 快速查询

dom4j 对 XPath 提供了非常好的支持,可以让你用非常简洁的语法直接定位到任意节点。

// ... 前面的代码相同,获取 document 对象
// 使用 XPath 获取所有书的作者
List<Node> authors = document.selectNodes("//book/author");
System.out.println("\n--- 使用 XPath 查询所有作者 ---");
for (Node node : authors) {
    System.out.println(node.getText());
}
// 使用 XPath 获取第一本书的价格
Node firstPriceNode = document.selectSingleNode("//book[1]/price");
if (firstPriceNode != null) {
    System.out.println("\n--- 使用 XPath 查询第一本书的价格 ---");
    System.out.println(firstPriceNode.getText());
}

任务 dom4j 方法/代码
创建解析器 SAXReader reader = new SAXReader();
读取文件 Document doc = reader.read(new File("path/to/file.xml"));
获取根元素 Element root = doc.getRootElement();
获取所有子元素 List<Element> children = root.elements();
获取指定名称的子元素 List<Element> books = root.elements("book");
获取第一个指定子元素 Element title = book.element("title");
获取元素文本 String text = title.getTextTrim();
获取属性 Attribute attr = book.attribute("category");
获取属性值 String value = book.attributeValue("category");
XPath 查询 List<Node> nodes = doc.selectNodes("//author");

dom4j 是一个非常灵活和强大的工具,掌握它可以让你在处理 XML 时游刃有余,对于大多数 Java 应用程序来说,它是处理 XML 的首选库之一。

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