java解析XML——SAX解析

来源:互联网 发布:mac office 2016破解版 编辑:程序博客网 时间:2024/06/05 20:30
为解决DOM的问题,出现了SAX。SAX ,事件驱动。当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。优点:不用事先调入整个文档,占用资源少;SAX解析器代码比DOM解析器代码小,适于Applet,下载。缺点:不是持久的;事件过后,若没保存数据,那么数据就丢了;无状态性;从事件中只能得到文本,但不知该文本属于哪个元素;使用场合:Applet;只需XML文档的少量内容,很少回头访问;机器内存少;
    SAX是Simple API for XML的缩写,它并不是由W3C官方所提出的标准,虽然如此,使用SAX的还是不少,几乎所有的XML解析器都会支持它。
      与DOM比较而言,SAX是一种轻量型的方法。我们知道,在处理DOM的时候,我们需要读入整个的XML文档,然后在内存中创建DOM树,生成DOM树上的每个Node对象。当文档比较
小的时候,这不会造成什么问题,但是一旦文档大起来,处理DOM就会变得相当费时费力。特别是其对于内存的需求,也将是成倍的增长,以至于在某些应用中使用DOM是一件很不划算的事(比如在applet中)。这时候,一个较好的替代解决方法就是SAX。
    SAX在概念上与DOM完全不同。它不同于DOM的文档驱动,它是事件驱动的,它并不需要读入整个文档,而文档的读入过程也就是SAX的解析过程。所谓事件驱动,是指一种基于
回调(callback)机制的程序运行方法。SAX基于事件的解析,解析器在一次读取XML文件中根据读取的数据产生相应的事件,由应用程序实现相应的事件处理逻辑,即它是一种“推”的解析方式;这种解析方法速度快、占用内存少,但是它需要应用程序自己处理解析器的状态,实现起来会比较麻烦。


具体示例:
(1)xml文件内容:在工程跟目录下建立xml/data1.xml文件,内容如下:
<students>    <student>        <name sex="man">小明</name>        <nickName>明明</nickName>        <age>20</age>        <address>北京</address>    </student>    <student>        <name sex="woman">小红</name>        <nickName>红红</nickName>        <age>20</age>        <address>上海</address>    </student>    <student>        <name sex="man">小亮</name>        <nickName>亮亮</nickName>        <age>30</age>        <address>广州</address>    </student>    <student-0>        <name sex="man">小亮-0</name>        <nickName>亮亮-0</nickName>        <age>200</age>        <address>广州-0</address>    </student-0></students>



(2)解析:
private void parseXml() {        long startTime = System.currentTimeMillis();        System.out.println("开始解析: " + startTime);        try {            InputStream is = new FileInputStream(xmlFile);            SAXParserFactory factory = SAXParserFactory.newInstance();            SAXParser newSAXParser = factory.newSAXParser();            MyHandler handler = new MyHandler();            // 将解析交给处理器            newSAXParser.parse(is, handler);        } catch (ParserConfigurationException e) {            e.printStackTrace();        } catch (SAXException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }        long finishTime = System.currentTimeMillis();        long countTime = finishTime - startTime;        System.out.println("结束解析: " + finishTime + "\nSax解析耗时:" + countTime);        for (Bean1 student : datas) {            System.out.println(student.toString());        }    }        class MyHandler extends DefaultHandler {        // 用于存储读取的临时变量        private String tempString;        private Bean1 bean;        /**         * 解析到文档开始调用,一般做初始化操作         *         * @throws SAXException         */        @Override        public void startDocument() throws SAXException {            super.startDocument();        }        /**         * 解析到文档末尾调用,一般做回收操作         *         * @throws SAXException         */        @Override        public void endDocument() throws SAXException {            super.endDocument();        }        /**         * 每读到一个元素就调用该方法         *         * @param uri         * @param localName         * @param qName         * @param attributes         * @throws SAXException         */        @Override        public void startElement(String uri, String localName, String qName, Attributes attributes)                throws SAXException {            if (qName.equals("student")) {                bean = new Bean1();            } else if (qName.equals("name")) {                // 获取name里面的属性                bean.setSex(attributes.getValue("sex"));            }            super.startElement(uri, localName, qName, attributes);        }        /**         * 读到元素的结尾调用         *         * @param uri         * @param localName         * @param qName         * @throws SAXException         */        @Override        public void endElement(String uri, String localName, String qName) throws SAXException {            if ("student".equals(qName)) {                datas.add(bean);            }            if (qName.equals("name")) {                bean.setName(tempString);            } else if (qName.equals("nickName")) {                bean.setName(qName);            } else if (qName.equals("age")) {                bean.setAge(qName);            } else if (qName.equals("adress")) {                bean.setAddress(qName);            }            super.endElement(uri, localName, qName);        }        /**         * 读到属性内容调用         *         * @param ch         * @param start         * @param length         * @throws SAXException         */        @Override        public void characters(char[] ch, int start, int length) throws SAXException {            tempString = new String(ch, start, length);            super.characters(ch, start, length);        }    }


    
    demo传送门:
https://github.com/215836017/ParseXML_java

https://github.com/215836017/ParserXML_android

注:上面Java的demo中用到的xml文件是当前目录下的xml/data1.xml文件。result.xml是生成的文件。data2.xml, data3.xml是用来比较解析时间的。
    Android的demo中用到xml文件是存放在手机根目录下的data1.xml文件。
原创粉丝点击