使用DOM解析XML的優點是用起來省事,但它的主要缺點是內存佔用太大。
另一種解析XML的方式是SAX。SAX是Simple API for XML的縮寫,它是一種基於流的解析方式,邊讀取XML邊解析,並以事件回調的方式讓調用者獲取數據。因爲是一邊讀一邊解析,所以無論XML有多大,佔用的內存都很小。
SAX解析會觸發一系列事件:
- startDocument:開始讀取XML文檔;
- startElement:讀取到了一個元素,例如;
- characters:讀取到了字符;
- endElement:讀取到了一個結束的元素,例如;
- 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
...
如果要讀取節點的文本,我們就必須在解析過程中根據startElement()和endElement()定位當前正在讀取的節點,可以使用棧結構保存,每遇到一個startElement()入棧,每遇到一個endElement()出棧,這樣,讀到characters()時我們才知道當前讀取的文本是哪個節點的。可見,使用SAX API仍然比較麻煩。
小結
SAX是一種流式解析XML的API;
SAX通過事件觸發,讀取速度快,消耗內存少;
調用方必須通過回調方法獲得解析過程中的數據。
謝謝觀看