共计 1709 个字符,预计需要花费 5 分钟才能阅读完成。
使用 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。
下载练习
小结
SAX 是一种流式解析 XML 的 API;
SAX 通过事件触发,读取速度快,消耗内存少;
调用方必须通过回调方法获得解析过程中的数据。
正文完
星哥玩云-微信公众号