自学内容网 自学内容网

Java中对xml文件解析并获取数据的方法——dom4j库和jaxen库的用法解读

最近在手写mybatis框架的时候,需要对xml文件进行解析,并读取其中的数据,来进行后续映射操作。对xml的文件的解析和数据获取用到了dom4j和jaxen两个库,所以系统的学习和整理一下两个库的知识点和用法。


一、dom4jjaxen 依赖概述

1.1 什么是 dom4j

dom4j 是一个开源的、灵活的 Java XML 解析和生成库。它提供了简单易用的 API 来读取、创建、修改和遍历 XML 文档。dom4j 支持多种 XML 解析方式(如 DOM、SAX 和 JAXP),并且性能优越,适用于处理各种规模的 XML 文件。

1.2 什么是 jaxen

jaxen 是一个基于 Java 的 XPath 引擎,用于在 XML 文档中执行 XPath 查询(dom4j库中,相关XPath查询的方法,都是调用了jaxen库中的方法)。XPath 是一种用于在 XML 文档中定位和选取节点的语言,jaxen 提供了强大的功能来解析和执行这些查询。jaxen 通常与 dom4j 配合使用,以增强 XML 数据的检索能力。

1.3 Maven 依赖引入

要在项目中使用 dom4jjaxen,需要在 pom.xml 文件中添加以下依赖:

<dependencies>
    <!-- dom4j 依赖 -->
    <dependency>
        <groupId>dom4j</groupId>
        <artifactId>dom4j</artifactId>
        <version>1.6.1</version>
    </dependency>

    <!-- jaxen 依赖 -->
    <dependency>
        <groupId>jaxen</groupId>
        <artifactId>jaxen</artifactId>
        <version>1.1.6</version>
    </dependency>
</dependencies>

二、dom4j 的使用详解

2.1 基本概念

dom4j 提供了丰富的 API 来操作 XML 文档。其核心类包括:

  • Document:表示整个 XML 文档。
  • Element:表示 XML 文档中的元素节点。
  • Attribute:表示元素的属性。
  • SAXReader:用于读取和解析 XML 文件。

2.2 解析 XML 文件

假设有一个名为 books.xml 的 XML 文件,内容如下:

<books>
    <book id="1">
        <title>Effective Java</title>
        <author>Joshua Bloch</author>
    </book>
    <book id="2">
        <title>Clean Code</title>
        <author>Robert C. Martin</author>
    </book>
</books>
示例代码:
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.util.List;

public class Dom4jExample {
    public static void main(String[] args) {
        try {
            // 创建 SAXReader 对象,读取 XML 文件
            SAXReader reader = new SAXReader();
            Document document = reader.read(new File("books.xml"));

            // 获取根元素
            Element root = document.getRootElement();
            System.out.println("根元素: " + root.getName());

            // 获取所有 book 元素
            List<Element> books = root.elements("book");
            for (Element book : books) {
                String id = book.attributeValue("id");
                String title = book.elementText("title");
                String author = book.elementText("author");

                System.out.println("书籍 ID: " + id);
                System.out.println("书名: " + title);
                System.out.println("作者: " + author);
                System.out.println("---------------------------");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
代码解释:
  1. 创建 SAXReader 对象:用于读取和解析 XML 文件。
  2. 读取 XML 文件reader.read(new File("books.xml")) 将 XML 文件解析为 Document 对象。
  3. 获取根元素document.getRootElement() 返回根元素 <books>
  4. 遍历 book 元素root.elements("book") 获取所有子元素 <book>,然后遍历每个 book 元素,读取其属性和子元素的文本内容。

2.3 生成 XML 文件

除了解析,dom4j 还可以用于生成 XML 文件。

示例代码:
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.XMLWriter;

import java.io.FileWriter;

public class GenerateXmlExample {
    public static void main(String[] args) {
        try {
            // 创建文档和根元素
            Document document = DocumentHelper.createDocument();
            Element root = document.addElement("books");

            // 创建第一个 book 元素
            Element book1 = root.addElement("book").addAttribute("id", "1");
            book1.addElement("title").setText("Effective Java");
            book1.addElement("author").setText("Joshua Bloch");

            // 创建第二个 book 元素
            Element book2 = root.addElement("book").addAttribute("id", "2");
            book2.addElement("title").setText("Clean Code");
            book2.addElement("author").setText("Robert C. Martin");

            // 将文档写入文件
            XMLWriter writer = new XMLWriter(new FileWriter("generatedBooks.xml"));
            writer.write(document);
            writer.close();

            System.out.println("XML 文件生成成功!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
代码解释:
  1. 创建文档和根元素:使用 DocumentHelper.createDocument() 创建一个新的 Document 对象,并添加根元素 <books>
  2. 添加子元素:通过 addElement 方法添加 <book> 元素,并设置其 id 属性。
  3. 设置子元素内容:为每个 book 元素添加 <title><author> 子元素,并设置其文本内容。
  4. 写入文件:使用 XMLWriter 将生成的 Document 对象写入到 generatedBooks.xml 文件中。

2.4 常用方法汇总

  • 读取和解析

    • SAXReader.read(File file):读取 XML 文件并返回 Document 对象。
    • Document.getRootElement():获取 XML 文档的根元素。
  • 操作元素

    • Element.addElement(String name):添加一个子元素。
    • Element.attributeValue(String name):获取元素的属性值。
    • Element.elementText(String name):获取子元素的文本内容。
    • Element.elements(String name):获取指定名称的所有子元素列表。
  • 生成和写入

    • DocumentHelper.createDocument():创建一个新的 Document 对象。
    • XMLWriter.write(Document document):将 Document 对象写入到指定的输出流。

三、jaxen 的使用详解

3.1 XPath 概述

XPath(XML Path Language)是一种用于在 XML 文档中定位和选取节点的语言。它通过路径表达式来导航 XML 文档的层次结构,可以高效地查找特定的元素或属性。

3.2 jaxendom4j 的结合使用

jaxen 通常与 dom4j 配合使用,利用 dom4j 的 XML 解析能力和 jaxen 的 XPath 查询能力,实现强大的 XML 数据检索功能。

3.3 使用 XPath 查询 XML

继续使用前面的 books.xml 文件,演示如何使用 jaxen 进行 XPath 查询。

示例代码:
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.xpath.XPath;

import java.io.File;
import java.util.List;

public class JaxenExample {
    public static void main(String[] args) {
        try {
            // 创建 SAXReader 对象,读取 XML 文件
            SAXReader reader = new SAXReader();
            Document document = reader.read(new File("books.xml"));

            // 创建 XPath 表达式,查找 title 为 "Clean Code" 的 book 元素
            XPath xpath = document.createXPath("//book[title='Clean Code']");
            List<Element> books = xpath.selectNodes(document);

            // 遍历查询结果
            for (Element book : books) {
                String id = book.attributeValue("id");
                String title = book.elementText("title");
                String author = book.elementText("author");

                System.out.println("找到的书籍 ID: " + id);
                System.out.println("书名: " + title);
                System.out.println("作者: " + author);
                System.out.println("---------------------------");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
代码解释:
  1. 创建 SAXReader 对象:用于读取和解析 XML 文件。
  2. 读取 XML 文件reader.read(new File("books.xml")) 将 XML 文件解析为 Document 对象。
  3. 创建 XPath 表达式//book[title='Clean Code'] 表示查找所有 book 元素,其子元素 title 的值为 "Clean Code"
  4. 执行查询xpath.selectNodes(document) 执行 XPath 查询,返回匹配的 book 元素列表。
  5. 遍历结果:遍历匹配的 book 元素,读取其属性和子元素的文本内容。

3.4 selectNodesselectSingleNode 方法详解

3.4.1 selectNodes()

selectNodes() 方法用于执行 XPath 查询并返回多个匹配的节点。其返回类型是 List<Element>,包含所有符合条件的元素。

示例:
// 查询所有书籍的标题
List<Element> titles = document.selectNodes("//book/title");
for (Element title : titles) {
    System.out.println("书名: " + title.getText());
}
解释:
  • XPath 表达式 //book/title 查找所有 book 元素下的 title 元素。
  • 返回所有匹配的 title 元素,并逐一输出其文本内容。
3.4.2 selectSingleNode()

selectSingleNode() 方法用于执行 XPath 查询并返回第一个匹配的节点。如果只需要一个结果,使用该方法更高效。

示例:
// 查询第一个书籍的标题
Element firstTitle = (Element) document.selectSingleNode("//book/title");
if (firstTitle != null) {
    System.out.println("第一本书的书名: " + firstTitle.getText());
}
解释:
  • XPath 表达式 //book/title 查找第一个匹配的 title 元素。
  • 返回第一个 title 元素,并输出其文本内容。

3.5 XPath 表达式常用语法

以下是一些常用的 XPath 表达式及其含义:

  • /(根节点开始)

    • 含义:从 XML 文档的根节点开始查询。
    • 示例/books/book/title 查找根元素 <books> 下的所有 <book> 元素的 <title> 子元素。
  • //(任意位置查找)

    • 含义:在 XML 文档的任意位置查找匹配的节点,不考虑层级结构。
    • 示例//title 查找文档中所有的 <title> 元素。
  • [@attribute='value'](属性过滤)

    • 含义:根据元素的属性值进行过滤。
    • 示例//book[@id='1'] 查找所有 id 属性值为 1<book> 元素。
  • [condition](条件过滤)

    • 含义:根据指定条件进行过滤。
    • 示例//book[title='Clean Code'] 查找所有 <book> 元素,其子元素 <title> 的值为 "Clean Code"
  • text()(文本节点)

    • 含义:选择元素的文本内容。
    • 示例//book/title/text() 获取所有 <title> 元素的文本内容。
具体示例:
// 1. 查找所有书籍的作者
List<Element> authors = document.selectNodes("//book/author");
for (Element author : authors) {
    System.out.println("作者: " + author.getText());
}

// 2. 查找 id 为 "2" 的书籍
Element bookWithId2 = (Element) document.selectSingleNode("//book[@id='2']");
if (bookWithId2 != null) {
    System.out.println("书名: " + bookWithId2.elementText("title"));
    System.out.println("作者: " + bookWithId2.elementText("author"));
}

// 3. 查找所有包含 "Java" 的书名
List<Element> javaBooks = document.selectNodes("//book[contains(title, 'Java')]");
for (Element book : javaBooks) {
    System.out.println("书名: " + book.elementText("title"));
}

3.6 /// 的区别详解

在 XPath 表达式中,/// 用于定义查询路径,它们的使用有显著区别:

3.6.1 /(根节点开始)
  • 含义:从 XML 文档的根节点开始,严格按照层级结构进行匹配。

  • 特点

    • 路径必须精确匹配文档的层级结构。
    • 不会跳过任何节点。
  • 示例

    <library>
        <books>
            <book id="1">
                <title>Effective Java</title>
                <author>Joshua Bloch</author>
            </book>
        </books>
    </library>
    

    XPath 表达式 /books/book/title

    • 解析:尝试从根节点 <books> 开始查找,但实际根节点是 <library>,因此无法匹配任何节点。
    • 结果:无匹配结果。

    XPath 表达式 /library/books/book/title

    • 解析:从根节点 <library> 开始,依次查找 <books><book><title>
    • 结果:匹配 <title>Effective Java</title>
3.6.2 //(任意位置查找)
  • 含义:在 XML 文档的任意位置查找匹配的节点,忽略层级结构。

  • 特点

    • 可以从文档的任何位置开始匹配。
    • 适用于结构复杂、层级深的 XML 文档。
  • 示例

    <library>
        <books>
            <book id="1">
                <title>Effective Java</title>
                <author>Joshua Bloch</author>
            </book>
        </books>
    </library>
    

    XPath 表达式 //book/title

    • 解析:在文档的任意位置查找 <book> 元素下的 <title> 元素。
    • 结果:匹配 <title>Effective Java</title>
3.6.3 使用场景比较
  • 使用 /

    • 当 XML 文档结构已知且需要精确匹配时使用。
    • 适用于简单、层级明确的 XML 文档。
  • 使用 //

    • 当 XML 文档结构复杂或层级不确定时使用。
    • 适用于需要从任意位置查找节点的场景。
3.6.4 示例比较
// 假设 XML 文档如下
/*
<library>
    <books>
        <book id="1">
            <title>Effective Java</title>
            <author>Joshua Bloch</author>
        </book>
    </books>
</library>
*/

// 使用 '/' 开始的 XPath 表达式
List<Element> titles1 = document.selectNodes("/books/book/title");
System.out.println("使用 '/' 查询结果数量: " + titles1.size()); // 输出: 0

// 使用 '//' 开始的 XPath 表达式
List<Element> titles2 = document.selectNodes("//book/title");
System.out.println("使用 '//' 查询结果数量: " + titles2.size()); // 输出: 1

// 输出书名
for (Element title : titles2) {
    System.out.println("书名: " + title.getText());
}

四、综合使用场景总结

4.1 场景 1:解析和读取 XML 文件

利用 dom4j 读取和解析 XML 文件,提取所需的数据。例如,读取配置文件、数据交换格式等。

示例:
// 读取并打印所有书籍的信息
List<Element> books = document.selectNodes("//book");
for (Element book : books) {
    String id = book.attributeValue("id");
    String title = book.elementText("title");
    String author = book.elementText("author");
    System.out.println("ID: " + id + ", 书名: " + title + ", 作者: " + author);
}

4.2 场景 2:生成和修改 XML 文件

使用 dom4j 动态生成或修改 XML 文件,例如生成数据导出文件、动态配置文件等。

示例:
// 修改现有 XML 文件,添加一本新书
Element newBook = root.addElement("book").addAttribute("id", "3");
newBook.addElement("title").setText("Design Patterns");
newBook.addElement("author").setText("Erich Gamma, et al.");

XMLWriter writer = new XMLWriter(new FileWriter("books.xml"));
writer.write(document);
writer.close();

4.3 场景 3:使用 XPath 查询复杂 XML 数据

利用 jaxendom4j 进行复杂的 XPath 查询,快速定位和提取特定节点或属性。

示例:
// 查找所有作者为 "Joshua Bloch" 的书籍
List<Element> booksByJoshua = document.selectNodes("//book[author='Joshua Bloch']");
for (Element book : booksByJoshua) {
    System.out.println("书名: " + book.elementText("title"));
}

// 查找所有书籍的标题,并按字母顺序排序
List<Element> sortedTitles = document.selectNodes("//book/title");
sortedTitles.sort((e1, e2) -> e1.getText().compareTo(e2.getText()));
for (Element title : sortedTitles) {
    System.out.println("书名: " + title.getText());
}

五、总结

5.1 dom4j 的核心优势

  1. 灵活性高:支持多种 XML 解析方式(DOM、SAX、JAXP)。
  2. API 简洁:提供直观、易用的 API 进行 XML 操作。
  3. 性能优越:适用于处理大规模 XML 文件。
  4. 功能丰富:支持 XML 的读取、创建、修改和遍历。

5.2 jaxen 的核心优势

  1. 强大的 XPath 支持:支持多种 XPath 版本和功能强大的查询能力。
  2. 高效查询:能够快速定位和选取 XML 文档中的特定节点或属性。
  3. 易于集成:与 dom4j 无缝集成,增强 XML 数据的检索能力。

5.3 selectNodesselectSingleNode 的使用建议

  • selectNodes

    • 用于需要获取多个匹配节点的场景。
    • 适用于批量处理和遍历多个节点。
  • selectSingleNode

    • 用于只需要获取第一个匹配节点的场景。
    • 更加高效,适用于单一结果的查询。

5.4 /// 的选择

  • 使用 /

    • 当 XML 文档结构已知且需要精确匹配时。
    • 适用于简单、层级明确的 XML 文档。
  • 使用 //

    • 当 XML 文档结构复杂或层级不确定时。
    • 适用于需要从任意位置查找节点的场景。

5.5 最佳实践

  1. 明确需求:在选择 XPath 表达式时,明确需要匹配的节点位置和条件。
  2. 优化查询:尽量使用具体的 XPath 表达式,避免不必要的广泛搜索,提高查询效率。
  3. 处理异常:在读取和写入 XML 文件时,妥善处理可能出现的异常,确保程序稳定性。
  4. 封装功能:将常用的 XML 操作封装成方法或类,提高代码的复用性和可维护性。

摊牌了,不装了,整理不易,我想要你手中的关注和赞


原文地址:https://blog.csdn.net/2301_79858914/article/details/142586198

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!