java · 2021-06-12 0

使用Digester解析XML

1.概述

Degister就是基于SAX实现,SAX提供了文件读取的底层接口,它是基于事件驱动类型

Degister类继承了DefaultHandler类

2.maven引入

<dependency>
    <groupId>commons-digester</groupId>
    <artifactId>commons-digester</artifactId>
    <version>2.1</version>
</dependency>

3.xml文件

foo.xml

<foo name="The Parent">
    <bar id="123" title="title one"/>
    <bar id="456" title="title two"/>
    <bar id="789" title="title two"/>
</foo>

4.bean

Foo.java

public class Foo {

    private String name;

    private List<Bar> barList = new ArrayList<>();

    public void addBar(Bar bar) {
        barList.add(bar);
    }

    public Bar findBar(int id) {
        for (Bar bar : barList) {
            if (bar.getId() == id) {
                return bar;
            }
        }
        return null;
    }

    public Iterator<Bar> getBars() {
        return barList.iterator();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Bar> getBarList() {
        return barList;
    }

    public void setBarList(List<Bar> barList) {
        this.barList = barList;
    }
}

Bar.java

public class Bar {

    private int id;

    private String title;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

5.使用Digester解析

Digester主要有startElement,endElement方法

  1. startElement方法中,根据标签名,查询规则,触发符合规则的begin方法

    1. Digeste把规则压入Digeste的matches中,Digeste的match为当前标签名
    2. ObjectCreateRule的begin方法,创建对象,把对象压入Digeste的stack中
    3. SetPropertiesRule的begin方法,为对象赋值属性值
  2. endElement方法中,根据标签名,查询规则,触发符合规则的body方法,然后触发符合规则的end方法

    1. Digeste把规则从matches中弹出,
    2. SetNextRule的end方法,查询Digeste的stack的栈顶第一个元素为子元素,第二个元素为父元素,调用父元素的方法,把子元素传入父元素的方法
    @Test
    public void test() throws IOException, SAXException {
        // 1.创建Digester对象实例
        Digester digester = new Digester();

        // 2.配置属性值
        digester.setValidating(false);

        // 3.设置匹配模式 规则
        // 设置规则,当遇到foo标签(<foo>),进行创建Foo对象
        // 把Foo对象压入Digeste的stack中,Digeste的match为foo
        digester.addObjectCreate("foo", "com.example.bean.Foo");
        // foo标签的属性和值(name="The Parent"),赋值给Digeste的stack顶的对象(此时是Foo对象)
        digester.addSetProperties("foo");
        // 设置规则。当遇到bar标签,match(此时Digeste的match为foo) + "/" + bar,即foo/bar,创建Bar对象
        // 把Bar对象压入Digeste的stack中,Digeste的match为foo/bar
        digester.addObjectCreate("foo/bar", "com.example.bean.Bar");
        // bar标签的属性和值(id="123" title="title one"),赋值给Digeste的stack顶的对象(此时是Bar对象)
        digester.addSetProperties("foo/bar");
        // 调用Foo对象的addBar方法
        digester.addSetNext("foo/bar", "addBar", "com.example.bean.Bar");

        // 4.开始解析
        Foo foo = (Foo) digester.parse(DIgesterTest.class.getClassLoader().getResourceAsStream("foo.xml"));

        // 5.打印解析结果
        System.out.println(foo.getName());

        for (Bar bar : foo.getBarList()) {
            System.out.println(bar.getId() + " " + bar.getTitle());
        }
    }