曝光臺 注意防騙
網曝天貓店富美金盛家居專營店坑蒙拐騙欺詐消費者
獨立的程序。下面首先給出要解析的文件:
程序清單6 - 5
第6章SAX 1.0: XML簡易API使用151 下載
注意parse( )的參數是一個U R L字符串。稍后會給出如何用一個文件名代替U R L。因為程序
涉及到數據的輸入和輸出,所以必須添加“ throws Exception”到countBooks( )方法以使發生錯
誤時發出警告。
還需要添加Java main( ) 方法以使程序成為一個獨立的應用程序。在m a i n方法中用n e w
BookCounter( )創建類的一個實例,然后調用對象的countBooks( )方法;同時對新建對象進行全
程跟蹤。代碼如下所示:
程序清單6 - 6
現在程序可以運行了:解析文檔直至運行結束(當然假設存在要被解析的文檔)。
唯一的不足是程序現在沒有產生輸出。為使程序更有用,需要添加一個方法對出現的
< b o o k >開始標簽進行計數,另外添加方法在文檔末尾輸出書的統計數目。這些方法使用了全局
變量c o u n t。
應用程序的最后版本如下所示。可以在我們的站點h t t p : / / w w w. w r o x . c o m /上關于本書的專欄
里找到本章中的代碼。
程序清單6 - 7
152使用XML 高級編程
下載
現在可以通過下列形式的命令從命令行運行應用程序:
程序會輸出給出的X M L文件中< b o o k >元素的數目。假設c : \ d a t a \ b o o k s . x m l文件中包含下列文
件(可以從h t t p : / / w w w. w r o x . c o m下載獲取本章中的代碼):
程序清單6 - 8
這樣在終端會顯示下列輸出:
第6章SAX 1.0: XML簡易API使用153 下載
3. DocumentHandler接口
如上面的例子所示,一個S A X應用程序的主要工作是在實現D o c u m e n t H a n d l e r接口的類里完
成的。通常我們會對比上面簡單例子包含的更多的事件感興趣,因此讓我們看一下構成接口的
其他方法。
(1) 文檔事件
首先,有一對方法標記文檔處理的開始與結束:
• startDocument( )
• endDocument( )
這兩個方法沒有參數和返回值。實際上,你通常可以不使用它們,因為程序開始進行的操
作一般可以在調用parse( )之前完成,而程序結束時要做的操作可以在parse( )返回值時完成。但
是在一個更復雜的應用程序中,你可能希望調用parse( )的應用程序是從D o c u m e n t H a n d l e r派生的
一不同的類,在此種情況下,這兩個方法有助于初始化變量和最后回收變量資源。
注意一個S A X解析器(P a r s e r類的一個簡單實例)應該同時只能解析一個X M L文檔。一旦它
完成了解析,可以再使用它解析其他文檔。如果你想同時解析幾個文檔,就需要為每個文檔創
建一個P a r s e r類的實例。你肯定想把這種文檔實例一一對應的規則應用到D o c u m e n t H a n d l e r,因
為在告知事件來源于哪個文檔的事件信息中也沒有進行什么其他操作。
(2) 元素事件
與文檔事件一樣,有一對可調用的方法用來標記文檔中每個元素的開始和結束標簽:
• startElement(String name,AttributeList attList)
• endElement(String name)
n a m e是指在元素開始和結束標簽中出現的名稱。
如果文檔對一個空元素使用簡短語法表示(即“ < t a g / >”),解析器將完全按你書寫
“< t a g > < / t a g >”的方式通報開始和結束標簽。這是因為X M L定義這兩個結構是同等的,所以應
用程序不需要知道使用的是哪一個。
在開始標簽里出現的屬性捆綁在一起成為A t t r i b u t e L i s t對象,同時立刻被應用程序處理。基
于事件的模式即始于此,你可能希望每個屬性在出現時都發出通報。A t t r i b u t e L i s t是S A X定義的
另一個接口。類似于解析器,它定義了一個實現接口的類:應用程序需要知道的是它為了獲取
各個屬性詳細信息時可以調用的方法。其中最有用的一個是:
• getValue(String name)
該方法在屬性存在時以字符串形式返回命名屬性的值,否則返回空。
關于A t t r i b u t e L i s t需要注意的是它僅在startElement( )方法的生命周期中有效。一旦該方法將
控制權返回給解析器,它可能(并且經常會)用不同的信息覆蓋A t t r i b u t e L i s t。如果想保留屬性
信息以備后用,你需要做一個副本。一種簡便的方式是使用S A X“h e l p e r”類A t t r i b u t e L i s t I m p l:
可以讓你創建另一個A t t r i b u t e L i s t作為已給出A t t r i b u t e L i s t的私有副本。
(3) 字符數據
X M L文檔中出現的字符數據一般通過下面的方法報告給應用程序:
• characters(char[] chars, int start, int len)
154使用XML 高級編程
下載
定義這種接口更多的是為了效率而不是方便。如果想把字符數據作為S t r i n g處理,你可以簡
單地構造一個字符串:
解析器可能已經創建了S t r i n g結構,但是在J a v a中創建新的對象是需要占用大量資源的,所
以它只給出指向字符存放位置的指針。
使用J a v a處理X M L的一個優點是J a v a和X M L都是采用統一碼標準字符集。不管開始的源文
檔中使用哪種字符編碼方式,以c h a r s數組形式傳遞的字符始終是本地化的J a v a統一碼字符。
重要的一點是解析器可以任意分解字符數據,也可以同時只傳送一部分。這就是說如果你
想在文檔中查找“g o l d”,那么下面的代碼就有錯誤:
程序清單6 - 9
為什么呢?因為可能文檔中出現了“ g o l d”字符串,但是是通過兩次或更多次characters( )
方法調用來告知應用程序。理論上,可能會有四個調用,分別對應“ g ” , “ o ” 和, “ “l d” ”。
問題的最壞情況是在測試中你可能沒有發現這種問題,因為實際上解析器很少用這種方式
分解文本。例如,它們可能僅當文本恰好處于一個4 0 9 6字節邊界時才分解文本(同時如果內存
中國航空網 www.k6050.com
航空翻譯 www.aviation.cn
本文鏈接地址:
XML高級編程上(59)