SAX解析XML

SAX解析XML

1.XML(Extensible Markup Language 可扩展标记语言),XML是一个以文本来描述数据的文档。

XML文档示例:


<people>
    <person personId="E01">
        <name>Tony Blairname>
        <address>10 Downing Street,London,UKaddress>
        <tel>(061) 98765tel>
        <fax>(061) 98765fax>
        <email>[email protected]email>
    person>
    <person personId="E02">
        <name>Tony Blairname>
        <address>10 Downing Street,London,UKaddress>
        <tel>(061) 98765tel>
        <fax>(061) 98765fax>
        <email>[email protected]email>
    person>
people>

2.XML的用途

(1)充当显示数据(以XML充当显示层)

(2)存储数据(存储层)的功能

(3)以XML描述数据,并在联系服务器与系统的其余部分之间传递

从某种角度讲,XML是数据封装和信息传递技术。

3.什么是SAX?

SAX是Simple Apl for XML的缩写

SAX是读取和操作XML数据更快捷,更轻量的方法,SAX允许你在读取文档时处理它,从而不必等待整个文档被存储后才采取操作,它不涉及DOM所必须得开销和概念跳跃,SAX api是一个基于事件的API ,适用于处理数据流,即随着数据的流动而一依次处理数据。SAX API在其解析你的文档时发生一定事件的时候会通知你,在你对其响应时,你不作保存的数据会被抛弃

SAX API中主要有四种处理事件的接口,ContenHandler、DTDHandler、EntiyResolver和ErrorHandler,由于DefaultHandler实现了这四个事件处理器接口。所以我们只需要继承DefaultHandler类就可以。

4.解析步骤

  • 首先,我们把XML文件对应的Person写出来
package com.lili.xmlAndJson;

/**
 * @author: QiJingJing
 * @create: 2021/7/17
 */
public class Person {
     
    private String personId;
    private String name;
    private String address;
    private String tel;
    private String fax;
    private String email;

    public Person(){
     }
    public Person(String personId, String name, String address, String tel, String fax, String email) {
     
        this.personId = personId;
        this.name = name;
        this.address = address;
        this.tel = tel;
        this.fax = fax;
        this.email = email;
    }

    public String getPersonId() {
     
        return personId;
    }

    public void setPersonId(String personId) {
     
        this.personId = personId;
    }

    public String getName() {
     
        return name;
    }

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

    public String getAddress() {
     
        return address;
    }

    public void setAddress(String address) {
     
        this.address = address;
    }

    public String getTel() {
     
        return tel;
    }

    public void setTel(String tel) {
     
        this.tel = tel;
    }

    public String getFax() {
     
        return fax;
    }

    public void setFax(String fax) {
     
        this.fax = fax;
    }

    public String getEmail() {
     
        return email;
    }

    public void setEmail(String email) {
     
        this.email = email;
    }

    @Override
    public String toString() {
     
        return "Person{" +
                "personId='" + personId + '\'' +
                ", name='" + name + '\'' +
                ", address='" + address + '\'' +
                ", tel='" + tel + '\'' +
                ", fax='" + fax + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}
  • 在测试类里面创建SAX解析器工厂对象

    // 1.创建一个SAX解析器工厂对象
    SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
    
  • 使用解析器工厂创建解析器实例

//2.通过工厂对象创建SAX解析器
SAXParser saxParser = saxParserFactory.newSAXParser();
  • 写一个事件侦听器类,需要继承DefaultHandler类,然后重写其中五个方法,每个方法的用途我已经标注

    package com.lili.xmlAndJson;
    
    import org.xml.sax.Attributes;
    import org.xml.sax.SAXException;
    import org.xml.sax.helpers.DefaultHandler;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @author: QiJingJing
     * @create: 2021/7/17
     */
    public class PersonHandler extends DefaultHandler {
           
        private List<Person> personList;
        private Person p; // 当前正在解析的对象
        private String tag;//用于记录当前正在解析的标签名
    
        public List<Person> getPersonList() {
           
            return personList;
        }
    
        // 开始解析文档时调用
        @Override
        public void startDocument() throws SAXException {
           
            super.startDocument();
            personList = new ArrayList<>();
            System.out.println("开始解析文档");
        }
    
        @Override
        public void endDocument() throws SAXException {
           
            super.endDocument();
            System.out.println("解析文档结束");
        }
        // 解析开始元素时使用
    
        /**
         * @param uri        命名空间
         * @param localName  不带前缀的标签名
         * @param qName      带前缀的标签名
         * @param attributes 当前标签的属性集合
         * @return: void
         * @author: QijingJing
         * @date: 2021/7/17
         */
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
           
            super.startElement(uri, localName, qName, attributes);
            if ("person".equals(qName)) {
           
                p = new Person();
                String personId = attributes.getValue("personId");
                p.setPersonId(personId);
            }
            tag = qName;
        }
    
        // 解析结束元素时使用
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
           
            super.endElement(uri, localName, qName);
            if ("person".equals(qName)) {
           
                personList.add(p);
            }
            tag = null;
        }
    
        // 解析文本内容时调用
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
           
            super.characters(ch, start, length);
            if (tag != null) {
           
                if ("name".equals(tag)) {
           
                    p.setName(new String(ch, start, length));
                } else if ("address".equals(tag)) {
           
                    p.setAddress(new String(ch, start, length));
                } else if ("tel".equals(tag)) {
           
                    p.setTel(new String(ch, start, length));
                } else if ("fax".equals(tag)) {
           
                    p.setFax(new String(ch, start, length));
                } else if ("email".equals(tag)) {
           
                    p.setEmail(new String(ch, start, length));
                }
            }
        }
    }
    
  • 在测试类里面创建一个侦听器对象,给出XML的地址,然后开始解析

    package com.lili.xmlAndJson;
    
    import org.junit.Test;
    import org.xml.sax.SAXException;
    
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.parsers.SAXParser;
    import javax.xml.parsers.SAXParserFactory;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    /**
     * @author: QiJingJing
     * @create: 2021/7/17
     */
    public class XmlTest {
           
        @Test
        public void test() throws ParserConfigurationException, SAXException, IOException {
           
            // 1.创建一个SAX解析器工厂对象
            SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
                //2.通过工厂对象创建SAX解析器
                SAXParser saxParser = saxParserFactory.newSAXParser();
                //3.创建一个数据处理器(需要我们自己来编码)
                PersonHandler personHandler = new PersonHandler();
                // 4.开始解析
                InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/lili/xmlAndJson/person.xml");
                saxParser.parse(is,personHandler);
            List<Person> personList = personHandler.getPersonList();
            personList.forEach(System.out::println);
        }
    }
    

输出如下:

开始解析文档
解析文档结束
Person{personId='E01', name='Tony Blair', address='10 Downing Street,London,UK', tel='(061) 98765', fax='(061) 98765', email='[email protected]'}
Person{personId='E02', name='Tony Blair', address='10 Downing Street,London,UK', tel='(061) 98765', fax='(061) 98765', email='[email protected]'}

Process finished with exit code 0

SAX解析的特点:

1.基于事件驱动

2.顺序读取,速度快

3.不能任意读取节点(灵活性差)

4.解析占用内存小

5.SAX更适用于在性能要求更高的设备上使用(Android开发中)

你可能感兴趣的:(javaSE,xml)