XML解析之ContentHandler介面
程式實現ContentHandler介面並且使用setContentHandler
方法,向 SAX 解析器註冊一個例項。解析器將使用該例項報告與基本文件相關的事件,如啟動和終止元素與字元資料。
此介面中的事件順序非常重要,它本身可映象文件中資訊的順序。例如,在 startElement 事件與相應的 endElement 事件之間,元素的所有內容(字元資料、處理指令和/ 或子元素)都將以一定順序出現。
此介面與現在不推薦使用的 SAX 1.0 DocumentHandler 介面相似,但它增加了對名稱空間和報告跳過的實體(在非驗證的 XML 處理器中)的支援。
在java.net
包中還有一個ContentHandler
import java.net.*;
import org.xml.sax.*;
實際上,不管怎樣 "import ...*" 通常標誌不簡潔的程式設計,因此,使用者應該將此作為一種功能而不是錯誤。
介面主要的方法
void setDocumentLocator(Locatorlocator)
接收用來查詢 SAX 文件事件起源的物件。
強烈建議(但不是絕對需要)使用 SAX 解析器來提供定位器:如果是這樣,則必須在呼叫 ContentHandler 介面中的任何其他方法之前呼叫此方法為應用程式提供定位器。
定位器允許應用程式確定任何與文件相關的事件的終止位置,即便是解析器不報告錯誤也是如此。通常情況下,應用程式將使用此資訊報告它自己的錯誤(例如與應用程式的業務規則不匹配的字元內容)。由定位器返回的資訊可能不足以供搜尋引擎使用。
注意,該定位器僅在呼叫 SAX 事件回撥期間,在 startDocument 返回之後,呼叫 endDocument 之前,返回正確的資訊。應用程式不應該嘗試在任何時間都使用它。
引數:
locator - 可以返回任何 SAX 文件事件位置的物件
另請參見:
Locator
void startDocument()throws SAXException
接收文件的開始的通知。在其他任何事件回撥(不包括 setDocumentLocator)之前,SAX 解析器僅呼叫此方法一次。
丟擲:
SAXException - 任何 SAX 異常,可能包裝另外的異常
另請參見:endDocument()
void endDocument() throws SAXException
接收文件的結尾的通知。
在此方法的說明和 ErrorHandler.fatalError(org.xml.sax.SAXParseException) 的說明之間存在著明顯的衝突。在未來的主版本中解決這一不明確問題之後,關於解析器報告 fatalError() 或丟擲異常後是否呼叫 endDocument() 這一點,客戶將會十分明確。
SAX 解析器僅呼叫此方法一次,並且它將是解析期間最後呼叫的方法。直到解析器放棄解析(由於不可恢復的錯誤)或到達輸入的結尾時,它才可以呼叫此方法。
丟擲:
SAXException - 任何 SAX 異常,可能包裝另外的異常
另請參見:startDocument()
void startPrefixMapping(String prefix,String uri)throws SAXException
開始字首 URI 名稱空間範圍對映。
此事件的資訊對於常規的名稱空間處理並非必需:當 http://xml.org/sax/features/namespaces 功能為 true(預設)時,SAX XML 讀取器將自動替換元素和屬性名稱的字首。
但是,有這樣幾種情況,應用程式需要在字元資料或屬性值中使用字首,但在這裡,字首不能自動地安全擴充套件;必要時,start/endPrefixMapping 事件將為應用程式提供所需資訊,以便應用程式本身可在這些上下文中擴充套件字首。
注意,不能保證 start/endPrefixMapping 事件相互之間能夠正確地巢狀:所有的 startPrefixMapping 事件將在相應的 startElement 事件之前立即發生,所有的 endPrefixMapping 事件將在相應的 endElement 事件之後立即發生,但在其他情況下不能保證其順序。
對於 "xml" 字首,永遠不應有 start/endPrefixMapping 事件,因為它是預宣告的和不可改變。
引數:
prefix - 宣告的名稱空間字首。對於沒有字首的預設元素名稱空間,使用空字串。
uri - 將字首對映到的名稱空間 URI
丟擲:
SAXException - 客戶端可能會在處理期間丟擲一個異常
另請參見:
void endPrefixMapping(java.lang.String), startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
void endPrefixMapping void endPrefixMapping(String prefix)throws SAXException
結束字首 URI 範圍的對映。
詳細資訊請參閱 startPrefixMapping。這些事件將始終在相應的 endElement 事件之後立即發生,但在其他情況下 endPrefixMapping 事件的順序不能保證。
引數:
prefix - 被對映的字首。當預設的對映範圍結束時,這是一個空字串。
丟擲:
SAXException - 客戶端可能會在處理期間丟擲一個異常
另請參見:startPrefixMapping(java.lang.String, java.lang.String), endElement(java.lang.String, java.lang.String, java.lang.String)
void startElement(String uri,String localName,String qName,Attributes atts)throws SAXException
接收元素開始的通知。
解析器在 XML 文件中的每個元素的開始呼叫此方法;對於每個 startElement 事件都將有相應的 endElement 事件(即使該元素為空時)。所有元素的內容都將在相應的 endElement 事件之前順序地報告。
此事件允許每個元素最多有以下三個名稱元件:
名稱空間 URI;
本地名稱;和
限定(字首)名。
可以提供它們中的部分或全部,具體如何取決於 http://xml.org/sax/features/namespaces 和 http://xml.org/sax/features/namespace-prefixes 屬性的值:
當名稱空間屬性為 true(預設)時,名稱空間 URI 和本地名稱是必需項,當名稱空間屬性為 false 時,則為可選項(如果指定一個值,兩個都必須指定);
當名稱空間字首屬性為 true 時,限定名是必需項,當名稱空間字首屬性為 false(預設值)時,則為可選項。
注意,所提供的屬性列表僅包括具有顯式值(指定的或預設的)的屬性:將忽略 #IMPLIED 屬性。僅在 http://xml.org/sax/features/namespace-prefixes 屬性為 true (預設情況下為 false,並且對 true 值的支援是可選項)時屬性列表才包括用於名稱空間宣告(xmlns* 屬性)的屬性。
與 characters() 一樣,屬性值可以具有需要不止一個 char 值的字元。
引數:
uri - 名稱空間 URI,如果元素沒有名稱空間 URI,或者未執行名稱空間處理,則為空字串
localName - 本地名稱(不帶字首),如果未執行名稱空間處理,則為空字串
qName - 限定名(帶有字首),如果限定名不可用,則為空字串
atts - 連線到元素上的屬性。如果沒有屬性,則它將是空 Attributes 物件。在 startElement 返回後,此物件的值是未定義的
丟擲:
SAXException - 任何 SAX 異常,可能包裝另外的異常
另請參見:
endElement(java.lang.String, java.lang.String, java.lang.String), Attributes, AttributesImpl
void endElement(String uri,String localName,String qName)throws SAXException
接收元素結束的通知。
SAX 解析器會在 XML 文件中每個元素的末尾呼叫此方法;對於每個 endElement 事件都將有相應的 startElement 事件(即使該元素為空時)。
有關名稱的資訊,請參見 startElement。
引數:
uri - 名稱空間 URI,如果元素沒有名稱空間 URI,或者未執行名稱空間處理,則為空字串
localName - 本地名稱(不帶字首),如果未執行名稱空間處理,則為空字串
qName - 限定的 XML 名稱(帶字首),如果限定名不可用,則為空字串
丟擲:
SAXException - 任何 SAX 異常,可能包裝另外的異常
void characters(char[]ch, intstart, intlength) throws SAXException
- 接收字元資料的通知。
解析器將呼叫此方法來報告字元資料的每個儲存塊。SAX 解析器能夠用單個儲存塊返回所有的連續字元資料,或者可以將該資料拆分成幾個儲存塊;但是,任何單個事件中的全部字元都必須來自同一個外部實體,以便定位器能夠提供有用的資訊。
應用程式不能嘗試在指定的範圍外從陣列中讀取資料。
單獨的字元可以由不止一個 Java
char
值組成。由於不能僅用十六位來表示字元,所以發生此情況的重要情形有兩種。一種情形是,字元用代理項對表示,使用兩個特殊的 Unicode 值。此類字元在所謂的 "Astral Planes" 中,程式碼點在 U+FFFF 之上。另一種情形涉及到複合字符,如由一個或多個重音字元構成的基本字元。編寫程式碼時不能假定一次讀入一個
char
的演算法將適用於字元單元;在某些情況下這些演算法將拆分一些字元。這與在什麼情況下 XML 允許有任意字元(如屬性值、處理指令資料、註解以及從此方法中報告的資料)相關。通常還與 Java 程式碼控制國際化的文字時相關;該問題不是 XML 獨有的。注意,有些解析器將使用
ignorableWhitespace
方法而不是此方法報告元素內容中的空白(驗證解析器必須這麼做)。 - 引數:
ch
- 來自 XML 文件的字元start
- 陣列中的開始位置length
- 從陣列中讀取的字元的個數 丟擲:SAXException
- 任何 SAX 異常,可能包裝另外的異常 另請參見:ignorableWhitespace(char[], int, int)
,Locator
void ignorableWhitespace(char ch,int start,int length)throws SAXException
接收元素內容中可忽略的空白的通知。
驗證解析器必須使用此方法來報告元素內容中的每塊空白(請參閱“W3C XML 1.0 Recommendation”中的 2.10 節):如果非驗證解析器能夠解析和使用內容模組,則這些非驗證解析器也可以使用此方法。
SAX 解析器能夠用單個儲存塊返回所有的連續空白,或者可以將該資料拆分成幾個儲存塊;但是,任何單個事件中的全部字元都必須來自同一個外部實體,以便定位器能夠提供有用的資訊。
應用程式不能嘗試在指定的範圍外從陣列中讀取資料。
引數:
ch - 來自 XML 文件的字元
start - 陣列中的開始位置
length - 從陣列中讀取的字元的個數
丟擲:
SAXException - 任何 SAX 異常,可能包裝另外的異常
另請參見:characters(char[], int, int)
void processingInstruction(String target,String data)throws SAXException
接收處理指令的通知。
解析器將為找到的每個處理指令呼叫一次此方法:注意,處理指令可以出現在主要文件元素的前面或後面。
SAX 解析器必須從不使用此方法報告 XML 宣告(XML 1.0 的 2.8 節)或文字宣告(XML 1.0 的 4.3.1 節)。
與 characters() 一樣,處理指令資料可以具有需要不止一個 char 值的字元。
引數:
target - 處理指令目標
data - 處理指令資料,如果未提供,則為 null。該資料不包括將其與目標分開的任何空白
丟擲:
SAXException - 任何 SAX 異常,可能包裝另外的異常。
void skippedEntity(String name) throws SAXException
接收跳過的實體的通知。將不為標記結構(如元素開始標記或標記宣告)內的實體引用呼叫此方法。(XML 建議書要求報告所跳過的外部實體。SAX 還報告內部實體擴充套件 / 非擴充套件,但不包括在標記結構內部。)
解析器將在每次跳過實體時呼叫此方法。如果非驗證處理器尚未看到宣告,則可以跳過實體(例如,因為該實體在外部 DTD 子集中宣告)。所有的處理器都可以跳過外部實體,但具體情況取決於 http://xml.org/sax/features/external-general-entities 和 http://xml.org/sax/features/external-parameter-entities 屬性的值。
引數:
name - 所跳過的實體的名稱。如果它是引數實體,則名稱將以 '%' 開頭,如果它是外部 DTD 子集,則將是字串 "[dtd]"
丟擲:
SAXException - 任何 SAX 異常,可能包裝另外的異常