java解析XML——SAX解析

为解决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文件。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值