使用SAX

使用DOM解析XML的优点是用起来省事,但它的主要缺点是内存占用太大。

另一种解析XML的方式是SAX。SAX是Simple API for XML的缩写,它是一种基于流的解析方式,边读取XML边解析,并以事件回调的方式让调用者获取数据。因为是一边读一边解析,所以无论XML有多大,占用的内存都很小。

SAX解析会触发一系列事件:

  • startDocument:开始读取XML文档;
  • startElement:读取到了一个元素,例如<book>
  • characters:读取到了字符;
  • endElement:读取到了一个结束的元素,例如</book>
  • endDocument:读取XML文档结束。

如果我们用SAX API解析XML,Java代码如下:

InputStream input = Main.class.getResourceAsStream("/book.xml");
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser saxParser = spf.newSAXParser();
saxParser.parse(input, new MyHandler());

关键代码SAXParser.parse()除了需要传入一个InputStream外,还需要传入一个回调对象,这个对象要继承自DefaultHandler

class MyHandler extends DefaultHandler {
    public void startDocument() throws SAXException {
        print("start document");
    }
    public void endDocument() throws SAXException {
        print("end document");
    }
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        print("start element:", localName, qName);
    }
    public void endElement(String uri, String localName, String qName) throws SAXException {
        print("end element:", localName, qName);
    }
    public void characters(char[] ch, int start, int length) throws SAXException {
        print("characters:", new String(ch, start, length));
    }
    public void error(SAXParseException e) throws SAXException {
        print("error:", e);
    }
    void print(Object... objs) {
        for (Object obj : objs) {
            System.out.print(obj);
            System.out.print(" ");
        }
        System.out.println();
    }
}

运行SAX解析代码,可以打印出下面的结果:

start document
start element:  book
characters:
start element:  name
characters: Java核心技术
end element:  name
characters:
start element:  author
...

如果要读取<name>节点的文本,我们就必须在解析过程中根据startElement()endElement()定位当前正在读取的节点,可以使用栈结构保存,每遇到一个startElement()入栈,每遇到一个endElement()出栈,这样,读到characters()时我们才知道当前读取的文本是哪个节点的。可见,使用SAX API仍然比较麻烦。

练习

下载练习:使用SAX解析XML (推荐使用IDE练习插件快速下载)

小结

SAX是一种流式解析XML的API;

SAX通过事件触发,读取速度快,消耗内存少;

调用方必须通过回调方法获得解析过程中的数据。

读后有收获可以支付宝请作者喝咖啡,读后有疑问请加微信群讨论

shiyongsax\_1.pngshiyongsax\_2.png

看完两件小事

如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:

  1. 关注我们的 GitHub 博客,让我们成为长期关系
  2. 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
  3. 关注公众号 「方志朋」,公众号后台回复「资源」 免费领取我精心整理的前端进阶资源教程

JS中文网是中国领先的新一代开发者社区和专业的技术媒体,一个帮助开发者成长的社区,目前已经覆盖和服务了超过 300 万开发者,你每天都可以在这里找到技术世界的头条内容。欢迎热爱技术的你一起加入交流与学习,JS中文网的使命是帮助开发者用代码改变世界

results matching ""

    No results matching ""