【Java Xml】Apache Commons Digester3解析

文章目录

概述

官网

写入查看另一篇:https://blog.csdn.net/qq_45742250/article/details/153191615

前期准备

maven

xml 复制代码
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-digester3 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-digester3</artifactId>
		<version>3.2</version>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.36</version>
</dependency>

使用

1、简单读取示例

test.xml

xml 复制代码
<Book>
    <Title>Java Programming</Title>
    <Author>John Doe</Author>
    <Price>39.99</Price>
</Book>

Book.java

java 复制代码
public class Book {
    private String title;
    private String author;
    private int price;

    // getter和setter方法省略
}

使用示例

java 复制代码
Digester digester = new Digester();
// 当遇到<Book>标签时,创建一个Book类的实例
digester.addObjectCreate("Book", Book.class);

// 当遇到<Book>下的<Title>标签时,将其内容设置到Book实例的title属性上
digester.addBeanPropertySetter("Book/Title", "title");

// 对<Author>和<Price>标签做同样的操作
digester.addBeanPropertySetter("Book/Author", "author");
digester.addBeanPropertySetter("Book/Price", "price");

// 文件路径
String filePath = "demo/test.xml";

// 存储文件内容
StringBuilder content = new StringBuilder();

try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
    String line;
    while ((line = br.readLine()) != null) {
        content.append(line).append(System.lineSeparator()); // 拼接每行
    }
    System.out.println(content);  // 打印文件内容
} catch (IOException e) {
    e.printStackTrace();
}

2、多个标签读取示例

library.xml

xml 复制代码
<Library>
    <Book>
        <Title>Java编程指南</Title>
        <Author>王五</Author>
        <Price>88</Price>
    </Book>
    <Book>
        <Title>高级Java技术</Title>
        <Author>赵六</Author>
        <Price>120</Price>
    </Book>
</Library>

Book.java

java 复制代码
public class Book {
    private String title;
    private String author;
    private int price;

    // getter和setter方法省略
}

Library.java

java 复制代码
public class Library {
    private List<Book> books = new ArrayList<>();

    // getter、setter、toString方法省略
    
    // 添加书籍到书单中
    public void addBook(Book book) {
        books.add(book);
    }
}

使用示例

java 复制代码
Digester digester = new Digester();
// 当遇到<Library>标签时,创建一个Book类的实例
digester.addObjectCreate("Library", Library.class);

digester.addObjectCreate("Library/Book", Book.class);
digester.addBeanPropertySetter("Library/Book/Title", "title");
digester.addBeanPropertySetter("Library/Book/Author", "author");
digester.addBeanPropertySetter("Library/Book/Price", "price");
// 将解析到的 Book 对象添加到 Library 的书单中(注意这里这个addSetNext,下文有解释,必须在已经添加号Library、Book类之后)
digester.addSetNext("Library/Book", "addBook");

// 文件路径
String filePath = "demo/library.xml";

// 存储文件内容
StringBuilder content = new StringBuilder();

try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
    String line;
    while ((line = br.readLine()) != null) {
        content.append(line).append(System.lineSeparator()); // 拼接每行
    }
    System.out.println(content);  // 打印文件内容
} catch (IOException e) {
    e.printStackTrace();
}

try {
    Library library = digester.parse(new StringReader(content.toString()));
    // 这里的xmlString是包含上面XML内容的字符串

    // 输出解析结果,检查是否正确
    System.out.println("library: " + library.toString());
} catch (IOException | SAXException e) {
    e.printStackTrace();
}

细节问题

addSetNext顺序

正确做法:

java 复制代码
Digester digester = new Digester();
// 当遇到<Library>标签时,创建一个Book类的实例
digester.addObjectCreate("Library", Library.class);

digester.addObjectCreate("Library/Book", Book.class);
digester.addBeanPropertySetter("Library/Book/Title", "title");
digester.addBeanPropertySetter("Library/Book/Author", "author");
digester.addBeanPropertySetter("Library/Book/Price", "price");
// (注意这里)将解析到的 Book 对象添加到 Library 的书单中
digester.addSetNext("Library/Book", "addBook");

错误做法:

java 复制代码
Digester digester = new Digester();
// 当遇到<Library>标签时,创建一个Book类的实例
digester.addObjectCreate("Library", Library.class);
// (注意这里)将解析到的 Book 对象添加到 Library 的书单中
digester.addSetNext("Library/Book", "addBook");

digester.addObjectCreate("Library/Book", Book.class);
digester.addBeanPropertySetter("Library/Book/Title", "title");
digester.addBeanPropertySetter("Library/Book/Author", "author");
digester.addBeanPropertySetter("Library/Book/Price", "price");

原因:

  1. addSetNext("Library/Book", "addBook") 被提前放置,这样在 Book 对象还没有创建时就试图将它添加到 Librarybooks 属性中。Book 对象尚未实例化,因此会引发错误或不正确的行为。
  2. addSetNext 需要确保在 Book 被创建之后才能执行,即 Book 对象已经存在,才能调用 LibraryaddBook 方法。

解决方案:

为了确保 Book 对象能够正确添加到 Library 中,应该遵循以下顺序:

  1. 首先创建 Library 对象。

  2. 然后创建 Book 对象,并为其设置属性。

  3. 最后使用 addSetNext 将创建好的 Book 对象添加到 Library 中。

参考

https://segmentfault.com/a/1190000044528235
https://juejin.cn/post/7066826274836054023
https://www.oryoy.com/news/jie-mi-apache-chu-li-xml-de-du-xie-ji-qiao-qing-song-jia-yu-fu-za-shu-ju-jie-gou.html

相关推荐
openHiTLS密码开源社区4 小时前
Apache开源许可证:深度解析与实践指南
apache·开源软件·贡献者许可·asf·基金会·专利授权·许可证
聪明的笨猪猪4 小时前
Java Redis “缓存设计”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
FIavor.4 小时前
我发送给Apifox是http://localhost:9002/goods/getByUserName?name=张三 为什么会是500哪里错了?
java·服务器·网络协议·http
ID_180079054734 小时前
京东获取整站实时商品详情数据|商品标题|数据分析提取教程
java·开发语言
微露清风5 小时前
系统性学习C++-第五讲-内存管理
java·c++·学习
计算机毕业设计木哥5 小时前
计算机毕业设计选题推荐:基于SpringBoot和Vue的快递物流仓库管理系统【源码+文档+调试】
java·vue.js·spring boot·后端·课程设计
235165 小时前
【LeetCode】146. LRU 缓存
java·后端·算法·leetcode·链表·缓存·职场和发展
聪明的笨猪猪5 小时前
Java Redis “运维”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
雪芽蓝域zzs5 小时前
uniapp开发 APP嵌入另一个APP打包的wgt文件,实现点击携带参数跳转到wgtAPP的某一个页面
uni-app·apache