杰瑞科技汇

dom4j如何高效解析Java中的XML?

目录

  1. 为什么选择 dom4j?
  2. 环境准备:添加依赖
  3. 核心 API 介绍
  4. 完整示例:解析 XML 文件
    • 准备 XML 文件
    • 编写 Java 解析代码
    • 代码详解
  5. 常用操作详解
    • 遍历节点
    • 读取节点属性和文本内容
    • 使用 XPath 快速查询
    • 创建和修改 XML

为什么选择 dom4j?

在 Java 中解析 XML 有多种方式,如 SAXDOMJDOMdom4j 相比它们有以下优势:

dom4j如何高效解析Java中的XML?-图1
(图片来源网络,侵删)
  • 性能卓越dom4j 使用了大量的接口和抽象类,设计上非常灵活,并且底层对性能做了优化,通常比 JDOM 和标准的 DOM 更快。
  • 功能强大:支持 XPathXSLTXML Schema 等高级 XML 标准。
  • API 简洁易用:API 设计直观,学习曲线相对平缓。
  • 社区活跃:被许多知名项目(如 Hibernate、Spring)所使用,文档和社区支持非常丰富。

环境准备:添加依赖

如果你使用的是 Maven,只需在 pom.xml 文件中添加 dom4j 的依赖即可:

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

如果你不使用 Maven,可以从 Maven 中央仓库 下载对应的 JAR 包,并添加到你的项目中。


核心 API 介绍

理解 dom4j 的核心类是上手的关键:

类/接口 描述
Document 代表整个 XML 文档,它是树结构的根,可以通过 SAXReaderDOMReader 创建。
Element 代表 XML 中的一个元素,这是 dom4j 中最重要的接口,几乎所有操作都围绕它展开,元素可以有子元素、属性和文本内容。
Attribute 代表元素的属性。
Node ElementAttributeDocument 等都实现了 Node 接口,它们都是 XML 树中的一个节点。
Branch DocumentElement 都实现了 Branch 接口,表示可以包含其他节点的分支节点。
Text 代表元素或属性的文本内容。
SAXReader 这是解析 XML 文档的核心类,它使用 SAX 解析器将 XML 文档读入内存,并构建 Document 对象。

完整示例:解析 XML 文件

这是一个最常见的需求:读取一个 XML 文件,并提取其中的信息。

dom4j如何高效解析Java中的XML?-图2
(图片来源网络,侵删)

准备 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>
</bookstore>

编写 Java 解析代码

我们将创建一个 Java 类,读取 books.xml,并打印出每本书的信息。

Dom4jParserDemo.java

dom4j如何高效解析Java中的XML?-图3
(图片来源网络,侵删)
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) {
        // 1. 创建 SAXReader 对象,这个对象是 dom4j 用于解析的核心
        SAXReader reader = new SAXReader();
        try {
            // 2. 读取 XML 文件,获取 Document 对象(整个 XML 文档的树形结构)
            // 注意:请确保 books.xml 文件位于项目的根目录下,或提供正确的路径
            Document document = reader.read(new File("books.xml"));
            // 3. 获取 XML 文档的根元素 <bookstore>
            Element rootElement = document.getRootElement();
            // 4. 遍历根元素下的所有 <book> 节点
            // element.elements("book") 会获取所有直接名为 "book" 的子元素
            List<Element> bookList = rootElement.elements("book");
            System.out.println("开始解析书籍信息...\n");
            for (Element book : bookList) {
                // 5. 获取节点的属性,category="children"
                String category = book.attributeValue("category");
                System.out.println("----- 开始解析一本书 -----");
                System.out.println("书籍类别: " + category);
                // 6. 获取子节点(如 <title>, <author> 等)的文本内容
                // element.element("title") 获取第一个名为 "title" 的子元素
                // elementText("title") 是一个便捷方法,直接获取指定子元素的文本内容
                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);
                // 7. 获取子节点的属性,lang="en"
                // 先获取 <title> 元素,再获取其属性
                Element titleElement = book.element("title");
                String lang = titleElement.attributeValue("lang");
                System.out.println("语言: " + lang);
                System.out.println("----- 解析完成 -----\n");
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
}

代码详解

  1. SAXReader reader = new SAXReader();: 创建解析器。
  2. reader.read(new File("books.xml"));: 解析指定的 XML 文件,返回一个 Document 对象,代表了整个 XML 的内存模型。
  3. document.getRootElement();: 获取 XML 的根元素(<bookstore>)。
  4. rootElement.elements("book");: 获取根元素下所有名为 book 的子元素,返回一个 List<Element>
  5. book.attributeValue("category");: 获取当前 book 元素的 category 属性的值。
  6. book.elementText("title");: 这是一个非常方便的方法,它会查找当前元素下第一个名为 title 的子元素,并直接返回其文本内容,避免了先获取 Element 再获取 Text 的繁琐步骤。
  7. book.element("title").attributeValue("lang");: 如果要获取子元素的属性,需要先通过 element() 方法获取该子元素,然后调用其 attributeValue() 方法。

常用操作详解

遍历节点(递归方式)

上面的示例是遍历已知子节点,如果需要遍历一个元素下的所有节点(包括未知名称的节点),可以使用递归。

// 这是一个递归遍历所有节点的方法
public void traverse(Element element) {
    // 1. 处理当前节点
    System.out.println("节点名称: " + element.getName());
    if (!element.isTextOnly()) {
        System.out.println("节点路径: " + element.getPath());
    }
    List<Attribute> attributes = element.attributes();
    for (Attribute attr : attributes) {
        System.out.println("  - 属性: " + attr.getName() + " = " + attr.getValue());
    }
    // 2. 递归处理子节点
    for (Iterator<Node> it = element.nodeIterator(); it.hasNext(); ) {
        Node node = it.next();
        if (node instanceof Element) {
            traverse((Element) node); // 递归
        } else if (node.getNodeType() == Node.TEXT_NODE) {
            // 处理文本节点,通常需要去除空白文本
            Text textNode = (Text) node;
            String text = textNode.getText().trim();
            if (!text.isEmpty()) {
                System.out.println("  - 文本内容: " + text);
            }
        }
    }
}

使用 XPath 快速查询

dom4jXPath 提供了完美的支持。XPath 是一种在 XML 文档中查找信息的语言,比手动遍历节点要简洁和高效得多。

示例:

// 假设我们已经有了 document 和 rootElement
// 1. 获取所有 <book> 节点
List<Node> books = document.selectNodes("//book");
// 2. 获取第一本书的 <title> 节点
Node firstTitle = document.selectSingleNode("//book[1]/title");
System.out.println("第一本书的标题: " + firstTitle.getText());
// 3. 获取所有价格大于 30 的书的作者
List<Node> authors = document.selectNodes("//book[price > 30]/author");
System.out.println("\n价格大于 30 的书的作者:");
for (Node author : authors) {
    System.out.println(author.getText());
}
// 4. 获取 lang 属性为 "en" 的所有标题
List<Node> enTitles = document.selectNodes("//book/title[@lang='en']");
System.out.println("\n语言为 'en' 的所有标题:");
for (Node title : enTitles) {
    System.out.println(title.getText());
}

创建和修改 XML

dom4j 不仅可以读取,还可以创建和修改 XML。

示例:创建一个新的 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 CreateXmlExample {
    public static void main(String[] args) throws IOException {
        // 1. 创建一个 Document 对象
        Document document = DocumentHelper.createDocument();
        // 2. 添加根元素 <students>
        Element root = document.addElement("students");
        // 3. 在根元素下添加子元素 <student>
        Element student1 = root.addElement("student");
        student1.addAttribute("id", "001");
        // 4. 在 <student> 下添加子元素和文本
        student1.addElement("name").addText("张三");
        student1.addElement("age").addText("20");
        // 5. 同样方式添加第二个学生
        Element student2 = root.addElement("student").addAttribute("id", "002");
        student2.addElement("name").addText("李四");
        student2.addElement("age").addText("21");
        // 6. 设置格式化输出
        OutputFormat format = OutputFormat.createPrettyPrint();
        // format.setEncoding("GBK"); // 如果需要指定编码
        // 7. 创建 XMLWriter 并写入文件
        XMLWriter writer = new XMLWriter(new FileWriter("new_students.xml"), format);
        writer.write(document);
        writer.close();
        System.out.println("XML 文件创建成功: new_students.xml");
    }
}

dom4j 是 Java 处理 XML 的利器,掌握它的关键在于:

  1. 理解树形模型:将 XML 看作一棵由 DocumentElementAttributeText 等节点组成的树。
  2. 熟练使用核心 API
    • SAXReader 用于读取和解析。
    • Document 代表整个文档
    • Element 代表元素,是操作的核心。
    • attributeValue()elementText() 是最常用的获取属性和文本内容的方法。
  3. 拥抱 XPath:对于复杂的查询,XPath 能让你用非常简洁的定位符快速找到目标节点,极大提升开发效率。

通过以上学习和实践,你就可以在 Java 项目中灵活地使用 dom4j 来解析、创建和操作 XML 数据了。

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