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

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

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

一、dom4j 和 jaxen 依赖概述

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 依赖引入

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

dom4j

dom4j

1.6.1

jaxen

jaxen

1.1.6

二、dom4j 的使用详解

2.1 基本概念

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

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

2.2 解析 XML 文件

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

Effective Java

Joshua Bloch

Clean Code

Robert C. Martin

示例代码:

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 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();

}

}

}

代码解释:

创建 SAXReader 对象:用于读取和解析 XML 文件。读取 XML 文件:reader.read(new File("books.xml")) 将 XML 文件解析为 Document 对象。获取根元素:document.getRootElement() 返回根元素 。遍历 book 元素:root.elements("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();

}

}

}

代码解释:

创建文档和根元素:使用 DocumentHelper.createDocument() 创建一个新的 Document 对象,并添加根元素 。添加子元素:通过 addElement 方法添加 元素,并设置其 id 属性。设置子元素内容:为每个 book 元素添加 和 <author> 子元素,并设置其文本内容。写入文件:使用 XMLWriter 将生成的 Document 对象写入到 generatedBooks.xml 文件中。</p> <p>2.4 常用方法汇总</p> <p>读取和解析:</p> <p>SAXReader.read(File file):读取 XML 文件并返回 Document 对象。Document.getRootElement():获取 XML 文档的根元素。</p> <p>操作元素:</p> <p>Element.addElement(String name):添加一个子元素。Element.attributeValue(String name):获取元素的属性值。Element.elementText(String name):获取子元素的文本内容。Element.elements(String name):获取指定名称的所有子元素列表。</p> <p>生成和写入:</p> <p>DocumentHelper.createDocument():创建一个新的 Document 对象。XMLWriter.write(Document document):将 Document 对象写入到指定的输出流。</p> <p>三、jaxen 的使用详解</p> <p>3.1 XPath 概述</p> <p>XPath(XML Path Language)是一种用于在 XML 文档中定位和选取节点的语言。它通过路径表达式来导航 XML 文档的层次结构,可以高效地查找特定的元素或属性。</p> <p>3.2 jaxen 与 dom4j 的结合使用</p> <p>jaxen 通常与 dom4j 配合使用,利用 dom4j 的 XML 解析能力和 jaxen 的 XPath 查询能力,实现强大的 XML 数据检索功能。</p> <p>3.3 使用 XPath 查询 XML</p> <p>继续使用前面的 books.xml 文件,演示如何使用 jaxen 进行 XPath 查询。</p> <p>示例代码:</p> <p>import org.dom4j.Document;</p> <p>import org.dom4j.Element;</p> <p>import org.dom4j.io.SAXReader;</p> <p>import org.dom4j.xpath.XPath;</p> <p>import java.io.File;</p> <p>import java.util.List;</p> <p>public class JaxenExample {</p> <p>public static void main(String[] args) {</p> <p>try {</p> <p>// 创建 SAXReader 对象,读取 XML 文件</p> <p>SAXReader reader = new SAXReader();</p> <p>Document document = reader.read(new File("books.xml"));</p> <p>// 创建 XPath 表达式,查找 title 为 "Clean Code" 的 book 元素</p> <p>XPath xpath = document.createXPath("//book[title='Clean Code']");</p> <p>List<Element> books = xpath.selectNodes(document);</p> <p>// 遍历查询结果</p> <p>for (Element book : books) {</p> <p>String id = book.attributeValue("id");</p> <p>String title = book.elementText("title");</p> <p>String author = book.elementText("author");</p> <p>System.out.println("找到的书籍 ID: " + id);</p> <p>System.out.println("书名: " + title);</p> <p>System.out.println("作者: " + author);</p> <p>System.out.println("---------------------------");</p> <p>}</p> <p>} catch (Exception e) {</p> <p>e.printStackTrace();</p> <p>}</p> <p>}</p> <p>}</p> <p>代码解释:</p> <p>创建 SAXReader 对象:用于读取和解析 XML 文件。读取 XML 文件:reader.read(new File("books.xml")) 将 XML 文件解析为 Document 对象。创建 XPath 表达式://book[title='Clean Code'] 表示查找所有 book 元素,其子元素 title 的值为 "Clean Code"。执行查询:xpath.selectNodes(document) 执行 XPath 查询,返回匹配的 book 元素列表。遍历结果:遍历匹配的 book 元素,读取其属性和子元素的文本内容。</p> <p>3.4 selectNodes 和 selectSingleNode 方法详解</p> <p>3.4.1 selectNodes()</p> <p>selectNodes() 方法用于执行 XPath 查询并返回多个匹配的节点。其返回类型是 List<Element>,包含所有符合条件的元素。</p> <p>示例:</p> <p>// 查询所有书籍的标题</p> <p>List<Element> titles = document.selectNodes("//book/title");</p> <p>for (Element title : titles) {</p> <p>System.out.println("书名: " + title.getText());</p> <p>}</p> <p>解释:</p> <p>XPath 表达式 //book/title 查找所有 book 元素下的 title 元素。返回所有匹配的 title 元素,并逐一输出其文本内容。</p> <p>3.4.2 selectSingleNode()</p> <p>selectSingleNode() 方法用于执行 XPath 查询并返回第一个匹配的节点。如果只需要一个结果,使用该方法更高效。</p> <p>示例:</p> <p>// 查询第一个书籍的标题</p> <p>Element firstTitle = (Element) document.selectSingleNode("//book/title");</p> <p>if (firstTitle != null) {</p> <p>System.out.println("第一本书的书名: " + firstTitle.getText());</p> <p>}</p> <p>解释:</p> <p>XPath 表达式 //book/title 查找第一个匹配的 title 元素。返回第一个 title 元素,并输出其文本内容。</p> <p>3.5 XPath 表达式常用语法</p> <p>以下是一些常用的 XPath 表达式及其含义:</p> <p>/(根节点开始):</p> <p>含义:从 XML 文档的根节点开始查询。示例:/books/book/title 查找根元素 <books> 下的所有 <book> 元素的 <title> 子元素。</p> <p>//(任意位置查找):</p> <p>含义:在 XML 文档的任意位置查找匹配的节点,不考虑层级结构。示例://title 查找文档中所有的 <title> 元素。</p> <p>[@attribute='value'](属性过滤):</p> <p>含义:根据元素的属性值进行过滤。示例://book[@id='1'] 查找所有 id 属性值为 1 的 <book> 元素。</p> <p>[condition](条件过滤):</p> <p>含义:根据指定条件进行过滤。示例://book[title='Clean Code'] 查找所有 <book> 元素,其子元素 <title> 的值为 "Clean Code"。</p> <p>text()(文本节点):</p> <p>含义:选择元素的文本内容。示例://book/title/text() 获取所有 <title> 元素的文本内容。</p> <p>具体示例:</p> <p>// 1. 查找所有书籍的作者</p> <p>List<Element> authors = document.selectNodes("//book/author");</p> <p>for (Element author : authors) {</p> <p>System.out.println("作者: " + author.getText());</p> <p>}</p> <p>// 2. 查找 id 为 "2" 的书籍</p> <p>Element bookWithId2 = (Element) document.selectSingleNode("//book[@id='2']");</p> <p>if (bookWithId2 != null) {</p> <p>System.out.println("书名: " + bookWithId2.elementText("title"));</p> <p>System.out.println("作者: " + bookWithId2.elementText("author"));</p> <p>}</p> <p>// 3. 查找所有包含 "Java" 的书名</p> <p>List<Element> javaBooks = document.selectNodes("//book[contains(title, 'Java')]");</p> <p>for (Element book : javaBooks) {</p> <p>System.out.println("书名: " + book.elementText("title"));</p> <p>}</p> <p>3.6 / 和 // 的区别详解</p> <p>在 XPath 表达式中,/ 和 // 用于定义查询路径,它们的使用有显著区别:</p> <p>3.6.1 /(根节点开始)</p> <p>含义:从 XML 文档的根节点开始,严格按照层级结构进行匹配。</p> <p>特点:</p> <p>路径必须精确匹配文档的层级结构。不会跳过任何节点。</p> <p>示例:</p> <p><library></p> <p><books></p> <p><book id="1"></p> <p><title>Effective Java

Joshua Bloch

XPath 表达式 /books/book/title:

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

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

解析:从根节点 开始,依次查找 。结果:匹配 <title>Effective Java

3.6.2 //(任意位置查找)

含义:在 XML 文档的任意位置查找匹配的节点,忽略层级结构。

特点:

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

示例:

Effective Java

Joshua Bloch

XPath 表达式 //book/title:

解析:在文档的任意位置查找 元素下的 元素。结果:匹配 <title>Effective Java

3.6.3 使用场景比较

使用 /:

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

使用 //:

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

3.6.4 示例比较

// 假设 XML 文档如下

/*

Effective Java

Joshua Bloch

*/

// 使用 '/' 开始的 XPath 表达式

List titles1 = document.selectNodes("/books/book/title");

System.out.println("使用 '/' 查询结果数量: " + titles1.size()); // 输出: 0

// 使用 '//' 开始的 XPath 表达式

List 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 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 数据

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

示例:

// 查找所有作者为 "Joshua Bloch" 的书籍

List booksByJoshua = document.selectNodes("//book[author='Joshua Bloch']");

for (Element book : booksByJoshua) {

System.out.println("书名: " + book.elementText("title"));

}

// 查找所有书籍的标题,并按字母顺序排序

List 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 的核心优势

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

5.2 jaxen 的核心优势

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

5.3 selectNodes 与 selectSingleNode 的使用建议

selectNodes:

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

selectSingleNode:

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

5.4 / 和 // 的选择

使用 /:

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

使用 //:

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

5.5 最佳实践

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

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