簡介
SAX是一個用於處理XML
事件驅動的“推”模型,雖然它不是W3C標準,但它卻是一個得到了廣泛認可的API。
SAX解析器不像DOM那樣建立一個完整的文檔樹,而是在讀取文檔時激活一系列事件,這些事件被推給事件處理器,然後由事件處理器提供對文檔內容的訪問。
常見的事件處理器有三種基本類型:
● 用於訪問XML DTD內容的DTDHandler;
● 用於低級訪問解析錯誤的ErrorHandler;
● 用於訪問文檔內容的ContentHandler,這也是最普遍使用的事件處理器。
SAX解析器讀取輸入文檔並在處理文檔時將每個事件推給文檔處理器(MyContentHandler)。與DOM相比,
SAX解析器能提供更好的性能優勢,它提供對XML文檔內容的有效低級訪問。SAX模型最大的優點是記憶體消耗小,因為整個文檔無需一次載入到記憶體中,這使SAX解析器可以解析大於
系統記憶體的文檔。另外,你無需像在DOM中那樣為所有節點創建對象。最後,SAX“推”模型可用於廣播環境,能夠同時註冊多個ContentHandler,並行接收事件,而不是在一個管道中一個接一個地進行處理。
SAX的缺點是你必須實現多個事件處理程式以便能夠處理所有到來的事件,同時你還必須在應用程式代碼中維護這個事件狀態,因為
SAX解析器不能交流元信息,如DOM的父/子支持,所以你必須跟蹤解析器處在文檔層次的哪個位置。如此一來,你的文檔越複雜,你的套用邏輯就越複雜。雖然沒有必要一次將整個文檔載入到記憶體中,但SAX解析器仍然需要解析整個文檔,這點和DOM一樣。
也許SAX面臨的最大問題是它沒有內置如XPath所提供的那些導航支持。再加上它的單遍解析,使它不能支持隨機訪問。這一限制也表現在名字空間上: 對有繼承名字空間的元素不做註解。這些限制使SAX很少被用於操作或修改文檔。
那些只需要單遍讀取內容的應用程式可以從SAX解析中大大受益。很多B2B和EAI應用程式將XML用做
封裝格式,接收端用這種格式簡單地接收所有數據。這就是SAX明顯優於DOM的地方:因高效而獲得高吞吐率。在SAX 2.0 中有一個內置的過濾機制,可以很輕鬆地輸出一個文檔子集或進行簡單的文檔轉換。
SAX
SAX,全稱Simple API for XML,既是指一種接口,也是指一個軟體包。SAX最初是由David Megginson採用
Java語言開發,之後SAX很快在Java開發者中流行起來。San現在負責管理其原始API的開發工作,這是一種公開的、
開放原始碼軟體。不同於其他大多數XML標準的是,SAX沒有語言開發商必須遵守的標準SAX參考版本。因此,SAX的不同實現可能採用區別很大的接口。
作為接口,SAX是
事件驅動型XML解析的一個標準接口(standard interface)不會改變,已被OASIS(Organization for the Advancement of Structured Information Standards)所採納。作為軟體包,SAX最早的開發始於1997年12月,由一些在網際網路上分散的程式設計師合作進行。後來,參與開發的程式設計師越來越多,組成了網際網路上的XML-DEV社區。五個月以後,1998年5月,SAX 1.0版由XML-DEV正式發布。目前,最新的版本是SAX 2.0。2.0版本在多處與1.0版本不兼容,包括一些類和方法的名字。
原理
SAX的工作原理簡單地說就是對文檔進行順序掃描,當掃描到文檔(document)開始與結束、元素(element)開始與結束、文檔(document)結束等地方時通知
事件處理函式,由事件處理函式做相應動作,然後繼續同樣的掃描,直至文檔結束。
大多數SAX實現都會產生以下類型的事件:
在文檔的開始和結束時觸發文檔處理事件。
在文檔內每一XML元素接受解析的前後觸發元素事件。
任何元數據通常都由單獨的事件交付。
在處理文檔的DTD或Schema時產生DTD或Schema事件。
產生錯誤事件用來通知主機應用程式解析錯誤。
SAX的優缺點
常用接口介紹
ContentHandler接口
ContentHandler是Java類包中一個特殊的SAX接口,位於
org.xml.sax包中。該接口封裝了一些對事件處理的方法,當XML解析器開始解析XML輸入文檔時,它會遇到某些特殊的事件,比如文檔的開頭和結束、元素開頭和結束、以及元素中的字元數據等事件。當遇到這些事件時,XML解析器會調用ContentHandler接口中相應的方法來回響該事件。
ContentHandler接口的方法有以下幾種:
void startDocument()
void endDocument()
void startElement(String uri, String localName, String qName, Attributes atts)
void endElement(String uri, String localName, String qName)
void characters(char[ ] ch, int start, int length)
DTDHandler接口
DTDHandler用於接收基本的DTD相關事件的通知。該接口位於
org.xml.sax包中。此接口僅包括DTD事件的注釋和未解析的實體聲明部分。
SAX解析器可按任何順序報告這些事件,而不管聲明注釋和未解析實體時所採用的順序;但是,必須在文檔處理程式的startDocument()事件之後,在第一個startElement()事件之前報告所有的DTD事件。
DTDHandler接口包括以下兩個方法
void startDocumevoid notationDecl(String name, String publicId, String systemId) nt()
void unparsedEntityDecl(String name, String publicId, String systemId, String notationName)
EntityResolver接口
EntityResolver接口是用於解析實體的基本接口,該接口位於org.xml.sax包中。
該接口只有一個方法,如下:
public InputSource resolveEntity(String publicId, String systemId)
解析器將在打開任何外部實體前調用此方法。此類實體包括在DTD內引用的外部DTD子集和外部參數實體和在文檔元素內引用的外部通用實體等。如果SAX應用程式需要實現自定義處理外部實體,則必須實現此接口。
ErrorHandler接口
ErrorHandler接口是SAX錯誤處理程式的基本接口。如果SAX應用程式需要實現自定義的錯誤處理,則它必須實現此接口,然後解析器將通過此接口報告所有的錯誤和警告。
該接口的方法如下:
void error(SAXParseException exception)
void fatalError(SAXParseException exception)
void warning(SAXParseException exception)
(1)用系統默認值來創建一個XMLReader(解析器):
XMLReader reader = XMLReaderFactory.createXMLReader();
(2)從給定的類名稱來創建一個XMLReader :
XMLReader reader = XMLReaderFactory.createXMLReader(
"org.apache.xerces.parsers.SAXParser");
(3)使用javax.xml.parsers包中的SAXParserFactory類和SAXParser類創建:
SAXParserFactory spFactory = SAXParserFactory.newInstance();
SAXParser sParser = spFactory.newSAXParser();
DefaultHandler類
DefaultHandler類是SAX2事件處理程式的默認基類。它實現了EntityResolver、DTDHandler、ContentHandler和ErrorHandler這四個接口。包含這四個接口的所有方法,所以我們在編寫事件處理程式時,可以不用直接實現這四個接口,而繼承該類,然後重寫我們需要的方法。如下:
import org.xml.sax.helpers.DefaultHandler;
public class TestDefaultHandler extends DefaultHandler{
public void startDocument() throws SAXException{
System.out.println("開始解析!"); }
public void endDocument() throws SAXException{
System.out.println("解析完成!"); }
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
System.out.println("元素名:"+qName);
}
public void endElement(String uri, String localName, String qName)
throws SAXException{
System.out.println("對"+qName+"的解析完成!");
}
}
XMLReader接口
XMLReader接口是使用回調讀取XML文檔的接口。XMLReader是XML解析器的SAX2驅動程式必須實現的接口。此接口允許應用程式設定和查詢解析器中的功能和屬性,註冊文檔的事件處理程式,以及對文檔的解析。如下:
import org.xml.sax.*;
public class TestXMLReader{
public TestXMLReader(){
try{
XMLReader reader = XMLReaderFactory.createXMLReader(
"org.apache.xerces.parsers.SAXParser");
System.out.println("創建解析器成功!");
//MyContentHandler是實現了ContentHandler接口的類
reader.setContentHandler(new MyContentHandler());
reader.setDTDHandler(new MyDTDHandler());
//對test.xml進行解析
reader.parse("test.xml");
System.out.println("解析完成!");
}catch(SAXException e){e.printStackTrace();}
}