SAX解析XML

何为Sax解析

Java解析XML通常有两种方式,DOM和SAX。DOM虽然是W3C的标准,提供了标准的解析方式,但它的解析效率一直不尽如人意,因为使用DOM解析XML时,解析器读入整个文档并构建一个驻留内存的树结构(节点树),然后您的代码才可以使用DOM的标准接口来操作这个树结构。但大部分情况下我们只对文档的部分内容感兴趣,根本就不用先解析整个文档,并且从节点树的根节点来索引一些我们需要的数据也是非常耗时的。

SAX是一种XML解析的替代方法。相比于文档对象模型DOM,SAX是读取和操作XML数据的更快速、更轻量的方法。SAX允许您在读取文档时处理它,从而不必等待整个文档被存储之后才采取操作。它不涉及DOM所必需的开销和概念跳跃。

SAX解析XML文档采用事件驱动模式。什么是事件驱动模式?它将XML文档转换成一系列的事件,由单独的事件处理器来决定如何处理。

基于事件驱动的处理模式主要是基于事件源和事件处理器(或者叫监听器)来工作的。一个可以产生事件的对象叫做事件源,而一个可以针对事件做出响应的对象就被叫做事件处理器。

首先我们需要了解Sax节点的种类

一种是ElementNode,一种是TextNode

<?xml version="1.0" encoding="utf-8" ?>
<people>
    <person id="1">
        <name>张三</name>
        <age>12</age>
        <tel>1111111</tel>
    </person>
    <person>
        <name>李四</name>
        <age>11</age>
        <tel>22222</tel>
    </person>
    <person>
        <name>王五</name>
        <age>10</age>
        <tel>33333</tel>
    </person>
</people>

其中像people person …就是ElementNode
张三 12则是TextNode

像Dom解析一样Sax解析也是分为固定的三个步骤

//1.获取解析器工厂
    SAXParserFactory factory = SAXParserFactory.newInstance(); 
//当然也可以直接声明工厂的实现类
    SAXParserFactory factory=new SAXParserFactoryImpl();
//2.获取解析器
    SAXParser parser = factory.newSAXParser();  
//3.解析XML
    parser.parse(xmlStream,new DefaultHandler(){

    }); 

注:Handler是解析时触发的事件,即事件源

在解析时Handler中需要注意的五个方法

//当读入XML时,会调用
public void startDocument()

//当读入一个节点时,会调用
public void startElement(String uri, String localName, String qName, Attributes attributes)

//当一个节点读取完毕时,会调用
public void endElement(String uri, String localName, String qName)

//当XML解析完毕时,会调用
 public void endDocument()

//处理节点中的文本内容则会用到
public void characters(char[] ch, int start, int length)

注:五个方法均会抛出SAXException

import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


public class SaxTest {
    static List<Person> people=new ArrayList();
    public static void main(String[] args)throws Exception {

        //1 工厂
        //SAXParserFactory spf=SAXParserFactory.newInstance();
        SAXParserFactory spf=new SAXParserFactoryImpl();
        //2 解析
        SAXParser sp=spf.newSAXParser();
        InputStream in=SaxTest.class.getClassLoader()
                .getResourceAsStream("com/dsj101/people.xml");

        sp.parse(in,/*3.解析事件*/new DefaultHandler(){

            /* @Override
             public void startDocument() throws SAXException {
                 System.out.println("开始解析文档内容了");
             }

             @Override
             public void endDocument() throws SAXException {
                 System.out.println("已解析完成");
             }*/
            private Person person;
            private String tag;

            @Override
            public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
                System.out.println(qName+"开始了");
                tag=qName;
                if(qName.equals("person")){
                    person=new Person();
                }

            }

            @Override
            public void endElement(String uri, String localName, String qName) throws SAXException {
                System.out.println(qName+"结束了");
                if (qName.equals("person")){
                    people.add(person);
                }
                tag=null;
            }

            @Override
            public void characters(char[] ch, int start, int length) throws SAXException {
                System.out.println("处理内容:"+new String(ch,start,length));
                if("name".equals(tag)){
                    person.setName(new String(ch,start,length));
                }
                if("age".equals(tag)){
                    person.setAge(Integer.parseInt(new String(ch,start,length)));
                }
                if("tel".equals(tag)){
                    person.setTel(new String(ch,start,length));
                }
            }
        });
        Collections.sort(people,(o1, o2) -> o2.getName().compareTo(o1.getName()));

        for (Person p :
                people) {
            System.out.println(p);
        }
        people=new ArrayList<>();
    }
}

最后来一个Python版的

import xml.sax

class MyHandler(xml.sax.ContentHandler):
    def __init__(self):
        self.person=None
        self.tag=None
    def startElement(self,name, attrs):
        self.tag=name
        if name == 'person':
            self.person = None
    def endElement(self,name):
        if name == 'person':
            global people
            people.append(self.person)
            self.person=None
        self.tag=None
    def characters(self,content):
        if "name" == self.tag:
            self.person.name == content
        if "age" == self.tag:
            self.person.age == int(content)
        if "tel" == self.tag:
            self.person.tel == content
parser = xml.sax.make_parser()  # 创建一个 XMLReader
# parser.setFeature(xml.sax.handler.feature_namespaces, 0)    # turn off namepsaces
parser.setContentHandler(MyHandler()) #设置内容事件处理器

parser.parse('people.xml')

最后的最后:
sax解析为流解析.顾名思义即遇到什么东西 执行某个方法(函数)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值