曝光臺 注意防騙
網曝天貓店富美金盛家居專營店坑蒙拐騙欺詐消費者
• 程序保存解析器提供的L o c a t o r對象的注解。
• 當錯誤發生時,程序在生成S A X E x c e p t i o n之前使用L o c a t o r對象輸出錯誤定位的有關信息。
注意應用程序必須支持沒有L o c a t o r的情況,因為并不要求解析器必須提供L o c a t o r。
• 程序包括最初的“初因”異常的細節信息( N u m b e r F o r m a t E x c e p t i o n),異常被封裝在
S A X P a r s e E x c e p t i o n里,也可以寫一些更精確的診斷信息。
• 把Moby Dick的價格“8 . 9 9”改為“A . 9 9”,下面是用x m l 4 j解析器得到的輸出:
本例中應用程序在產生異常之前生成了一條包含位置信息的消息,然后當異常在高層被捕
獲時生成真正的錯誤消息。另一種方法是把位置信息作為異常的一部分來傳遞,可以通過產生
S A X P a r s e E x c e p t i o n而不是通常的S A X E x c e p t i o n做到這一點。然而應用程序必須處理沒有L o c a t o r
的情況,這時產生S A X P a r s e E x c e p t i o n就不是很方便。一個替代的方法是當解析器不提供L o c a t o r
時讓應用程序創建自己缺省的L o c a t o r(不包含什么有用信息)。
6. 保持上下文信息
迄今為止從兩個例子中可以看出在解析處理過程中D o c u m e n t H a n d l e r一般需要保持一些上下
文信息。第一個例子是對元素累加計數;第二個例子是由D o c u m e n t H a n d l e r明確當前是否是在一
個含有c a t e g o r y = " f i c t i o n "的< b o o k >元素里。
幾乎所有實際的S A X應用程序都需要保持一些此類的上下文信息。它經常適于明確當前元
素的嵌套情況,很多情況下也用于了解當前處理數據所有祖先元素的屬性。
明顯的數據結構是堆棧,因為堆棧很自然地在遇到元素開始標簽時添加元素信息,而在遇
到元素結束標簽時刪除元素信息。當然堆棧需要比存儲整個文檔少得多的內存,因為堆棧中需
要的最大條目數就是元素的最大嵌套層數。即使在一個龐大復雜的文檔里,嵌套層數也很少超
過1 0個左右。
如果更改一下對前面程序例子的要求,我們會看到堆棧是如何發揮作用的。這次允許書籍
目錄包含多卷書目,每卷有一個價格并且整個集合有一個價格。在計算平均價格時,我們想知
道整個集合的價格而不是個別卷的價格。
源文檔如下所示(也可以在h t t p : / / w w w. w r o x . c o m站點得到):
程序清單6 - 1 2
162使用XML 高級編程
下載
處理這種情況的方法是在程序里引入另一個標記,當遇到< v o l u m e >開始標簽時設置標記,
當遇到< / v o l u m e >結束標簽時取消標記;如果標記被設置了,程序將忽略< p r i c e >元素。但是這種
編程風格很快就導致了標記的增多和i f - t h e n - e l s e條件判斷的復雜嵌套。更好的方法是把關于當前
打開元素的所有信息放到一個堆棧里,這樣就可以按需查詢。
下面是新的程序版本:
程序清單6 - 1 3
第6章SAX 1.0: XML簡易API使用163 下載
164使用XML 高級編程
下載
下面是期望的輸出:
看起來好像是我們費了好大力氣維護這個堆棧而并沒有取得多少效果。然而這是值得的。
所有實際的應用程序變得越來越復雜,擁有一個支持這種邏輯而不破壞程序結構的數據結構是
有益的。注意條件判斷,如isFiction( )和i s Volume( ),現在成為應用于上下文數據結構的方法而
不是應用于當事件發生時保持的標記。隨著需要判斷條件數量的增多,可以編寫更多這樣的方
法而不增加startElement( )和endElement( )方法的復雜度。
6.3 SAX的高級特性
目前涉及到的S A X特性對9 0 %的S A X應用程序來說已經足夠了。但是了解一些其他的特性是
有所幫助的,以備需要時使用。本章節給出了這些特性及其設計目標的概觀。
第6章SAX 1.0: XML簡易API使用165 下載
6.3.1 可選擇的源輸入
目前在我們的例子中,被解析的文檔是以U R L的形式描述的。一般情況下,就U R L可以描
述的資源的范圍而言,這已經足夠了。它允許文檔存于本地或遠程文件中,或由We b服務器動
態生成。
1. 從字節流或字符流中獲取輸入
有時想把由另一個程序生成的的X M L流而不是存放于文件中的X M L提交給解析器。例如,
X M L可能是存放于關系數據庫中,或者是一個E D I消息翻譯程序的輸出,或者是嵌入在一個非
X M L格式文件或消息中的X M L片段。你不想僅僅為了讓解析器可以讀取你的文檔而不得不去編
寫X M L文件(或安裝We b服務器)。
為了處理這種情況, S A X 允許以字符流或字節流的形式提交X M L輸入。S A X提供了
I n p u t S o u r c e類以生成所有可能的輸入源。
例如,假設程序想解析存放于一個字符串里的X M L,它剛被通過J D B C從關系數據庫中讀取。
下面的代碼完成上述工作:
程序清單6 - 1 4
I n p u t S o u r c e是S A X發行版提供的一個類(而不是一個接口)。應用程序可以設置源輸入的許
多詳細信息,這些信息是相互排斥的。包括提供U R L,R e a d e r,I n p u t S t r e a m,編碼名稱或一個
“公共標識”。(在S A X中的公共標識就像和在X M L自身規范中一樣令人費解:沒有什么線索可以
確定解析器應該對公共標識真正做些什么。但是后面會看到,應用程序可以使用公共標識。)
為什么S A X需要提供兩種可選的內存數據, I n p u t S t r e a m和R e a d e r?
I n p u t S t r e a m是一個字節流。X M L標準對字節流如何轉換為統一碼字符流提供了許多規則,
例如包括編碼屬性(它是文檔內容開始xml 聲明的一部分)。為把字節轉換成字符,完全由標準
J a v a庫實現這種轉換是不夠好的,因為它們不理解這些規則,當然也不能指望它們讀取編碼屬性。
如果X M L從二進制源獲得,在處理完編碼屬性后,希望把字節流傳遞給解析器直接解釋。
而R e a d e r是一個統一碼字符流。如果已經有了字符形式的數據,我們不想僅僅為了解析器能
中國航空網 www.k6050.com
航空翻譯 www.aviation.cn
本文鏈接地址:
XML高級編程上(62)