SAX解析XML

来源:互联网 发布:mac qq 讨论组 删除人 编辑:程序博客网 时间:2024/06/04 01:02

何为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.saxclass 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 == contentparser = xml.sax.make_parser()  # 创建一个 XMLReader# parser.setFeature(xml.sax.handler.feature_namespaces, 0)    # turn off namepsacesparser.setContentHandler(MyHandler()) #设置内容事件处理器parser.parse('people.xml')

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

原创粉丝点击