使用 Apache Digester 的注解方式解析 xml

本文介绍了如何使用Apache Digester库解析XML文件到Java对象,通过注解定义解析规则,简化了XML解析过程。示例展示了解析包含属性的XML和属性分离的XML,涉及对象创建、属性设置、链式处理等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

解析 xml,你可以采用 Java 原生支持的 sax、DOM 或者第三方的 dom4j 等。虽然提供了各式各样的解析方式,但是解析一个复杂的 xml 所编写的 Java 代码是非常麻烦的。

而 Apache 的 commons 项目中 Digester 项目解决了这个问题,它可以很轻易地将xml文件解析成Java对象,让你直接去使用,而你仅仅需要去预定义一份解析规则,Digester 的内部采用 SAX 来解析 XML 文件。

对于解析规则,可以采用如下三种方式

  • Java的方式
  • xml的方式
  • annotation的方式

常用的规则:

  • ObjectCreate,创建对象实例。
  • SetProperties,将标签属性(Attribute)与要创建的对象的属性相关联。
  • BeanPropertySetter,将标签所包含标签与要创建的对象的属性相关联。
  • SetNext,设置遇到下一个标签时的动作。

一、解析前的准备工作

1、创建一个 springboot 项目

引入如下两个依赖,主要是 digester 的依赖,lombok 用来简化实体中的 get/set

<!--   digester 解析  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>
            <optional>true</optional>
        </dependency>
2、准备好两种格式的 xml 文件
1、第一种,标签中包含属性的 xml
<?xml version="1.0" encoding="UTF-8"?>

<school>
  <class code="001" Title="一年一班">
	<teacher name="张三"/>
    <student code="01" name="小明"/>
	<student code="02" name="小红"/>
  </class>

   <class code="002" Title="一年二班">
	<teacher name="李四"/>
    <student code="01" name="小王"/>
  </class>
</school>

2、第二种,标签和属性分离的
<?xml version="1.0" encoding="UTF-8"?>

<books>
    <book>
        <title>西游记</title>
        <description>西天取经的故事</description>
        <person>孙悟空</person>
        <person>猪八戒</person>
    </book>
    <book>
        <title>三国演义</title>
        <description>历史故事</description>
        <person>诸葛亮</person>
        <person>刘备</person>
    </book>
</books>

二、开始解析

1、解析 xml 标签中包含属性的 school.xml
1、创建相关 java 实体对象,用来接收解析的 xml
/**
 * @author wuxiongwei
 * @date 2021/2/23 14:08
 * @Description
 */
@Data
@ObjectCreate(pattern = "school")
public class SchoolGroup {

    private List<Class> list = new ArrayList();

    @SetNext
    public void addNext(Class clazz) {
        this.list.add(clazz);
    }

}
/**
 * @author wuxiongwei
 * @date 2021/2/23 14:07
 * @Description
 */
@Data
//当碰到 xml 中的 school/class 标签时,创建一个对象
@ObjectCreate(pattern = "school/class")
public class Class {
    /**
     * SetProperty 适用于接收如下格式
     *  <class code="001" Title="一年一班">
     */
    @SetProperty(pattern = "school/class")
    private String code;

    /**
     * <class code="001" Title="一年一班">
     *   如果 xml 中标签的属性名称与对象属性名称不一致,可以使用 attributeName ,标识当前这个对象属性 title 接收 xml 标签的 Title 属性
     */
    @SetProperty(pattern = "school/class",attributeName = "Title")
    private String title;

    private Teacher teacher = new Teacher();

    private List<Student> studentList = new ArrayList<>();



    // 当碰到 school/class 标签下的 student 标签的处理
    @SetNext
    public void addNext(Student student) {
        this.studentList.add(student);
    }

    // 当碰到 school/class 标签下的 teacher 标签的处理
    @SetNext
    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }



}
/**
 * @author wuxiongwei
 * @date 2021/2/23 14:10
 * @Description
 */
@Data
@ObjectCreate(pattern = "school/class/teacher")
public class Teacher {

    @SetProperty(pattern = "school/class/teacher")
    private String name;

}
/**
 * @author wuxiongwei
 * @date 2021/2/23 14:10
 * @Description
 */
@Data
@ObjectCreate(pattern = "school/class/student")
public class Student {

    @SetProperty(pattern = "school/class/student")
    private String code;

    @SetProperty(pattern = "school/class/student")
    private String name;

}

2、关键解析类
/**
 * @author wuxiongwei
 * @date 2021/2/23 14:21
 * @Description
 */
public class SchoolDigester {
    private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

    public static void main(String[] args) {

        // 定义要解析的 XML 的路径
        File file = null;

        try {
            file = ResourceUtils.getFile("classpath:school.xml");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        Digester digester = DigesterLoader.newLoader(new FromAnnotationsRuleModule() {
            @Override
            protected void configureRules() {
                // 这里只添加HolidayInfoXmlGroup即可
                bindRulesFrom(SchoolGroup.class);
            }
        }).newDigester();

        try {
            SchoolGroup parse = digester.parse(file);
            for (Class aClass : parse.getList()) {
                LOGGER.info("学校xml解析信息如下"+aClass.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
            LOGGER.info("load error:",e.getMessage());
        }
    }
}
3、解析数据

在这里插入图片描述

2、解析 xml 标签和属性分离的 book.xml

同样,先把接收的对象创建

1、创建接收 xml 的实体对象
/**
 * @author wuxiongwei
 * @date 2021/2/23 14:08
 * @Description
 */
@Data
@ObjectCreate(pattern = "books")
public class BookGroup {

    private List<Book> list = new ArrayList();


    @SetNext
    public void addNext(Book clazz) {
        this.list.add(clazz);
    }

}
/**
 * @author wuxiongwei
 * @date 2021/2/23 14:07
 * @Description
 */
@Data
@ObjectCreate(pattern = "books/book")
public class Book {

    /**
     * 适用于如下这种 xml 标签格式
     *    <book>
     *         <title>西游记</title>
     *     </book>
     */
    @BeanPropertySetter(pattern = "books/book/title")
    private String title;

    @BeanPropertySetter(pattern = "books/book/description")
    private String description;


    private List<Person> personList = new ArrayList<>();

    @SetNext
    public void addNext(Person clazz) {
        this.personList.add(clazz);
    }
}

/**
 * @author wuxiongwei
 * @date 2021/2/23 14:34
 * @Description
 */
@Data
@ObjectCreate(pattern = "books/book/person")
public class Person {

    @BeanPropertySetter(pattern = "books/book/person")
    private String name;

}

2、关键解析类
/**
 * @author wuxiongwei
 * @date 2021/2/23 14:21
 * @Description
 */
public class BookDigester {
    private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());



    public static void main(String[] args) {

        // 定义要解析的 XML 的路径
        File file = null;

        try {
            file = ResourceUtils.getFile("classpath:book.xml");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        Digester digester = DigesterLoader.newLoader(new FromAnnotationsRuleModule() {
            @Override
            protected void configureRules() {
                // 这里只添加HolidayInfoXmlGroup即可
                bindRulesFrom(BookGroup.class);
            }
        }).newDigester();

        try {
            BookGroup parse = digester.parse(file);
            for (Book aClass : parse.getList()) {
                LOGGER.info("书籍xml解析信息如下"+aClass.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
            LOGGER.info("load error:",e.getMessage());
        }
    }
}
3、解析结果

在这里插入图片描述

源码地址

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值