J2ME中的XML語法分析利器KXML_JSP教程
推薦:J2ME編程中三種低級用戶界面事件處理技術(shù)1、 覆蓋keyPressed方法 在繼承了Canvas的界面中,如果需要進行按鍵的處理,我們只需要在該類中覆蓋Canvas類里面的這個方法,當手機按鍵被按下時,系統(tǒng)會自動調(diào)用該方法,并把被按
Enhydra的KXML是一個只占很小存儲空間的XML語法分析程序,對于J2ME應(yīng)用程序非常適合。它有一個非常獨特的DOM操作方法和被稱為Pull的語法分析方法。
在開發(fā)一個用于J2ME設(shè)備的多人游戲項目。在這個應(yīng)用程序中,服務(wù)器和設(shè)備之間的通訊原來被編碼成由"&"分隔的鍵值對,這樣從服務(wù)器檢索變量會很快,但是當我開始處理更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)和嵌套的數(shù)據(jù)結(jié)構(gòu)時,我發(fā)現(xiàn)這種方法并不適用。在這種情況,它會變得很難寫數(shù)據(jù)并且容易出錯。
為了解決這問題,我決定使用XML重新編寫應(yīng)用程序的數(shù)據(jù)傳輸部分。對于我來說,XML是一個自然而然的選擇,不僅僅因為我已經(jīng)使用它在以前的一個項目中編寫了通過網(wǎng)絡(luò)向applet中傳送信息的程序,而且因為XML確實很容易調(diào)試和編寫。當然,它還讓你使用一種很豐富的格式來結(jié)構(gòu)化這些數(shù)據(jù)。然而,讓我意想不到的是我竟為我的編程工具箱找到一顆珍貴的寶石。
KXML是一個被設(shè)計用于J2ME設(shè)備的簡化類庫,雖然它也可以被用于其它需要小型XML語法分析程序的環(huán)境,比如Applet。KXML是一個Enhydra維護的項目,支持下面的性能:
支持XML名稱空間
用"松散"模式分析HTML或其它SGML格式
占用很少的存儲空間(21 kbps)
基于Pull的分析
支持XML寫操作
可選的DOM支持
可選的WAP支持
在本文中,詳細說明其中的一些特點,尤其是Pull分析和DOM操作,而且我將告訴你如何檢查KXML在內(nèi)存中操作的效果。本文中的兩個MIDlet例程都有完整的源代碼,可以向你說明如何使用KXML(點擊下載)。在KToolBar 1.04工程中不包含KXML類庫--你必須從http://KXML.enhydra.org/取得類庫,然后把壓縮文件放在工程的"lib"目錄下。
使用XML工作
有兩個常見的使用XML工作的方法:操作DOM或者捕捉語法分析事件。操作DOM是一個與XML相互作用的簡單方法,通常這個XML是一棵完整的XML樹,被解析成一個存放在存儲器中的節(jié)點結(jié)構(gòu),你可以遍歷這棵樹。它非常簡單易用,但是因為整棵樹存在于存儲器中造成存儲器的負擔(dān)。
第二種方法在捕捉語法分析事件中,每當語法分析程序遇到數(shù)據(jù)中的特定結(jié)構(gòu),它就會遍歷XML數(shù)據(jù),然后把結(jié)果發(fā)回前面注冊的一個事件監(jiān)聽器中。比如說,當語法分析程序遇到一個起始標記,如<html>,那么事件監(jiān)聽器將接收一個事件,通知它這個情況,并且向它傳遞任何所需的信息。實現(xiàn)這種策略的語法分析程序被稱為push語法分析程序,因為這個語法分析程序把事件"推入"一個監(jiān)聽器中。
KXML支持DOM語法分析和操作,但是不支持push語法分析。取而代之,它使用一種稍微不同的稱為"Pull"的分析方法。與push語法分析相反,Pull語法分析讓程序員從語法分析程序中"拉"出下一個事件。在push語法分析中,你必須維護你正在分析的當前數(shù)據(jù)的狀態(tài),然后基于傳送到監(jiān)聽器的事件,恢復(fù)任何以前的狀態(tài),并且當你轉(zhuǎn)換到一個不同的狀態(tài)時保存新的狀態(tài)。Pull語法分析使處理狀態(tài)改變更加容易,因為你可以發(fā)送分析器到不同的函數(shù),維護它們自己的狀態(tài)變量。
Pull語法分析
讓我們來研究一個例子,看看KXML如何做一個Pull語法分析程序。演示程序名為KXMLDemo_Pull。它將使用一個Pull語法分析程序查看一個包含通訊錄信息的文件。下面給出源代碼中比較重要的幾行,我還給出了注釋。
1.XmlParser parser = null;
2......
3.parser = new XmlParser( new InputStreamReader( 1this.getClass().getResourceAsStream(resfile_name) ));
第三行創(chuàng)建了一個XmlParser,把它傳到一個InputStream中。這個語法分析程序反復(fù)調(diào)用,直到出現(xiàn)END_DOCUMENT事件。
1.while ( (event = parser.read()).getType() != Xml.END_DOCUMENT ) {
2. ...
3.if (name != null && name.equals("address")) {
4. ...
5. parseAddressTag( parser );
第三行判斷事件是否以一個<address>標記開始,第五行傳送語法分析器到控制語法分析程序的"parseAddressTag"。
1.while ((event = parser.peek()).getType() != Xml.END_DOCUMENT) {
2....
3. if (type == Xml.END_TAG && name.equals("address")) {
4. return;
5. }
6....
7. ParseEvent next = parser.read();
8.
9. // if it's not a text event then skip it
10. if (next.getType() != Xml.TEXT) {
11. continue;
12. }
13....
14. System.err.println(name ": " text);
上面的這段代碼在"parseAddressTag"中循環(huán),直到找到與<address>對應(yīng)的終止標記。如果它遇到其它任何標記,那么標記名和標記內(nèi)容就會被打印到控制臺上。因此,如果找到標記<name>Robert Cadena</name>,你將看到下面的控制臺輸出:
name: Robert Cadena
一旦找到<address>的終止標記(8- 10行),控件被返回調(diào)用函數(shù),然后又開始查找<address>。
如你所見,使用Pull語法分析程序非常容易,并且能夠傳送語法分析程序到另一個函數(shù),然后在文檔中查找元素。你并不局限于分析資源文件;你還可以使用HttpConnection把這個函數(shù)傳遞到http InputStream。這把你從讀取InputStream、保存內(nèi)容、分析內(nèi)容等操作中解放了出來,一切都由KXML為你完成。
DOM處理
Pull語法分析特別適用于當你需要維護非常小的存儲空間的時候,因為發(fā)出事件的文檔只有一部分存在于內(nèi)存中。換句話說,如果你感興趣的特定數(shù)據(jù)段是文檔中部的幾百個字節(jié),那么前面的幾百個字節(jié)就不必保存在內(nèi)存中了。
但是如果你能夠節(jié)省一些內(nèi)存,你可以使用另一個版本的KXML語法分析程序,它包含對DOM的支持。 DOM是保存在內(nèi)存中的整個文檔樹,每個標記都被分離成節(jié)點(Node)對象。 你可以遍歷這個文檔樹,然后根據(jù)需要取得數(shù)據(jù)。
工程中的另一個MIDlet,KXMLDemo_dom,做了同樣的事情。它讀取一個通訊錄,然后把內(nèi)容打印到控制臺,但是這次它使用了DOM。下面給出源代碼中比較重要的幾行.
1.Document doc = new Document();
2....
3.parser = new XmlParser( isr );
4.doc.parse( parser );
第一行創(chuàng)建了一個文檔,保存XML樹。第三行從一個名為isr的InputStreamReader中創(chuàng)建一個KXML語法分析程序。第四行傳送這個語法分析程序到文檔,然后讓文檔開始分析。XML被遞歸分析,直到到達文檔的結(jié)尾。當分析調(diào)用退出時,整個文檔被裝入內(nèi)存,這時你就可以操作它了。
1.Element root = doc.getRootElement();
2.int child_count = root.getChildCount();
3....
4.for (int i = 0; i < child_count ; i ) {
5....
6. Element kid = root.getElement(i);
7.
8. if (!kid.getName().equals("address")) {
9. continue;
10. }
因為我們知道<address>元素是根元素的直接子元素,我們可以遍歷根元素的子元素,尋找address標記,如果子元素不是一個address 標記,則返回。
1.int address_item_count = kid.getChildCount();
2.
3. for (int j = 0; j < address_item_count ; j ) {
4....
如果我們找到了address子元素,我們開始遍歷它的子元素,并把這些子元素的內(nèi)容打印出來。不幸的是,你不能只是使用kid.getElement("name"),因為如果這個元素不存在的話,那么你將得到一個RuntimeException。所以我建議只有當你知道XML文檔中存在你所有需要的所有字段時才使用這個方法。
檢查你的內(nèi)存
根據(jù)經(jīng)驗,當你不能確保你的應(yīng)用程序的結(jié)構(gòu),并且你需要保持內(nèi)存被占用情況較低時,你應(yīng)該使用Pull語法分析程序。當你有足夠內(nèi)存并且可能需要通過添加或移動標記的方式操作文檔時,可以使用DOM。
如果你想看看這兩種方法使用內(nèi)存的情況,在KtoolBar中打開工程,使用內(nèi)存監(jiān)視器(Edit-->Preferences:Monitoring Tag)。 當你運行MIDlet,你將看到內(nèi)存監(jiān)控窗口彈出,有圖形和數(shù)字表示內(nèi)存的使用情況。 運行每一個應(yīng)用程序,然后觀察綠線上升,這表示你的應(yīng)用程序消耗的內(nèi)存量。 你將看到Pull應(yīng)用程序比DOM應(yīng)用程序使用內(nèi)存少一些。雖然本例中的兩個MIDlet之間的區(qū)別不是非常大,但是如果一個MIDlet用DOM方式遍歷一個更大的文件,那么它將消耗更多內(nèi)存。
分享:J2ME 3D編程的第一個3D程序參考WTK2.2提供的demo,完成了第一個3D程序,雖然很簡單,而且有些問題還不是很清楚,還是把代碼共享出來和愿意學(xué)習(xí)J2ME 3D編程的朋友一起學(xué)習(xí)。 關(guān)于代碼的編譯和運行說明如下:
- jsp response.sendRedirect不跳轉(zhuǎn)的原因分析及解決
- JSP指令元素(page指令/include指令/taglib指令)復(fù)習(xí)整理
- JSP腳本元素和注釋復(fù)習(xí)總結(jié)示例
- JSP FusionCharts Free顯示圖表 具體實現(xiàn)
- 網(wǎng)頁模板:關(guān)于jsp頁面使用jstl的異常分析
- JSP頁面中文傳遞參數(shù)使用escape編碼
- 基于jsp:included的使用與jsp:param亂碼的解決方法
- Java Web項目中連接Access數(shù)據(jù)庫的配置方法
- JDBC連接Access數(shù)據(jù)庫的幾種方式介紹
- 網(wǎng)站圖片路徑的問題:絕對路徑/虛擬路徑
- (jsp/html)網(wǎng)頁上嵌入播放器(常用播放器代碼整理)
- jsp下顯示中文文件名及絕對路徑下的圖片解決方法
- 相關(guān)鏈接:
- 教程說明:
JSP教程-J2ME中的XML語法分析利器KXML
。