目前,XML已經(jīng)廣泛應(yīng)用于數(shù)據(jù)交換領(lǐng)域,xml是基于純文本的,具有優(yōu)秀的跨平臺特性。本文將講述如何在J2ME中解析XML進行數(shù)據(jù)傳輸。
??? XML寫法比較簡單,而且非常便于人來閱讀。但是必須在客戶端和服務(wù)器端有XML的解析器才可以正常通信,由于初期的移動信息設(shè)備內(nèi)存和處理器上的不足,所以在MIDP1.0中并沒有提供對XML的支持。隨著內(nèi)存和處理器的提高,對XML的支持成為了可能。在JSR182中提供了XML的解析器,但是這并不是標準MIDP中的API需要特定的實現(xiàn)才可以支持。幸運的是有第三方的API對解析xml提供了支持,比較有名的是kxml和nanoxml。 ??? 使用XML之前,你必須考慮好是不是必須用它來傳輸數(shù)據(jù),因為解析xml是比較耗費資源的,尤其是在CPU和內(nèi)存的資源都很寶貴的條件下。如果我們能使用DataInputStream和DataOutputStream傳輸?shù)脑捑捅M量不要使用XML。XML的解析器有兩種,一種是確認性的,他在解析之前會對xml的文檔進行有效性的驗證,確保這是應(yīng)用程序需要的。另一種則是非確認性的,他不做驗證工作直接進行解析,無疑這樣的速度會快。kxml和nanoxml都是這樣的解析器。它們也存在差別,kxml是增量解析器他會一點一點的解析,這樣在解析大的文檔的時候會效率比較高。nanoxml是一步解析器,一次就把文檔解析完,如果文檔很大的話,這無疑會耗費很大的內(nèi)存。要使用kxml你可以從http://www.kxml.org 下載得到,在http://nanoxml.sourceforge.net?你可以下載nanoxml。 ??? 要使用kxml,你必須首先得到一個XmlParser實例,它用Reader作為構(gòu)造器的參數(shù): try { ??? Reader??? r = .....; ??? XmlParser parser = new XmlParser( r ); } catch( java.io.IOException e ){ ??? // handle exception.... } 如果你的xml文檔存儲在String內(nèi)的話你可以使用ByteArrayInputStream和InputStreamReader: String??? xml = "<a>some xml</a>"; ByteArrayInputStream bin = ??????????? new ByteArrayInputStream( xml.getBytes() ); XmlParser parser = new XmlParser( new InputStreamReader( bin ) ); 當(dāng)從網(wǎng)上接收數(shù)據(jù)的時候可以這樣: HttpConnection??? conn = .....; InputStreamReader doc = ???????? new InputStreamReader( conn.openInputStream() ); XmlParser parser = new XmlParser( doc ); 得到parser實例后我們就可以調(diào)用read方法進行解析了,read方法會返回一個ParseEvent,通過判斷他的類型我們就可以解析xml了。 try { ??? boolean keepParsing = true; ??????? ??? while( keepParsing ){ ??????? ParseEvent event = parser.read(); ? ??????? switch( event.getType() ){ ??????????? case Xml.START_TAG: ??????????????? ..... // handle start of an XML tag ??????????????? break; ??????????? case Xml.END_TAG: ??????????????? ..... // handle end of an XML tag ??????????????? break; ??????????? case Xml.TEXT: ??????????????? ..... // handle text within a tag ??????????????? break; ??????????? case Xml.WHITESPACE: ??????????????? ..... // handle whitespace ??????????????? break; ??????????? case Xml.COMMENT: ??????????????? ..... // handle comment ??????????????? break; ??????????? case Xml.PROCESSING_INSTRUCTION: ??????????????? ..... // handle XML PI ??????????????? break; ??????????? case Xml.DOCTYPE: ??????????????? ..... // handle XML doctype ??????????????? break; ??????????? case Xml.END_DOCUMENT: ??????????????? ..... // end of document; ??????????????? keepParsing = false; ??????????????? break; ??????? } ??? } } catch( java.io.IOException e ){ } 如果想使用nanoxml,那么你首先要創(chuàng)建一個kXMLElement實例,然后調(diào)用parseFromReader、parseString或者parseCharArray。由于他是一步解析器,那么它會把整個文檔解析完后生成一個Object tree。每個節(jié)點都是一個kXMLElement的實例,通過調(diào)用getChildren等方法可以在這棵樹上導(dǎo)航。 HttpConnection??? conn = .....; InputStreamReader doc = ???????? new InputStreamReader( conn.openInputStream() ); kXMLElement?????? root = new kXMLElement(); try { ??? root.parseFromReader( doc ); } catch( kXMLParseException pe ){ } catch( IOException ie ){ } 下面是一個J2ME的應(yīng)用程序簡單演示了如何解析xml。如果有時間可以寫寫復(fù)雜的測試程序。你可以從如下地址下載源代碼:XMLTest. 里面包括了kxml和nanoxml的源代碼,如果想得到最新的源代碼請參考他們的官方網(wǎng)站,在本站提供了kxml的在線API package com.ericgiguere.techtips; import java.io.*; import java.util.*; import javax.microedition.lcdui.*; import javax.microedition.midlet.*; import nanoxml.*; import org.kxml.*; import org.kxml.parser.*; /** ?* Simple MIDlet that demonstrates how an XML document can be ?* parsed using kXML or NanoXML. ?*/ public class XMLTest extends MIDlet { ??? // Our XML document -- normally this would be something you ??? // download. ??? ??? private static String xmlDocument = ??????? "<list><item>apple</item>" + ????????????? "<item>orange</item>" + ????????????? "<item>pear</item></list>"; ????????????? ??? private Display display; ??? private Command exitCommand = new Command( "Exit", ?????????????????????????????????????????????? Command.EXIT, 1 ); ?????????????????????????????????????????????? ??? public XMLTest(){ ??? } ??? ??? protected void destroyApp( boolean unconditional ) ?????????????????????? throws MIDletStateChangeException { ??????? exitMIDlet(); ??? } ??? ??? protected void pauseApp(){ ??? } ??? ??? protected void startApp() throws MIDletStateChangeException { ??????? if( display == null ){ // first time called... ??????????? initMIDlet(); ??????? } ??? } ??? ??? private void initMIDlet(){ ??????? display = Display.getDisplay( this ); ??????? ??????? String [] items; ??????? ??????? //items = parseUsingNanoXML( xmlDocument ); ??????? items = parseUsingkXML( xmlDocument ); ??????? ??????? display.setCurrent( new ItemList( items ) ); ??? } ??? ??? public void exitMIDlet(){ ??????? notifyDestroyed(); ??? } ??? ??? // Parses a document using NanoXML, looking for ??? // "item" nodes and returning their content as an ??? // array of strings. ??? ??? private String[] parseUsingNanoXML( String xml ){ ??????? kXMLElement root = new kXMLElement(); ??????? try { ??????????? root.parseString( xml ); ??????????? ??????????? Vector list = root.getChildren(); ??????????? Vector items = new Vector(); ??????????? ??????????? for( int i = 0; i < list.size(); ++i ){ ??????????????? kXMLElement node = ???????????????????? (kXMLElement) list.elementAt( i ); ??????????????? String????? tag = node.getTagName(); ??????????????? ??????????????? if( tag == null ) continue; ??????????????? if( !tag.equals( "item" ) ) continue; ??????????????? ??????????????? items.addElement( node.getContents() ); ??????????? } ??????????? ??????????? String[] tmp = new String[ items.size() ]; ??????????? items.copyInto( tmp ); ??????????? return tmp; ??????? } ??????? catch( kXMLParseException ke ){ ??????????? return new String[]{ ke.toString() }; ??????? } ??? } ??? ??? // Parses a document using kXML, looking for "item" ??? // nodes and returning their content as an ??? // array of strings. ??? ??? private String[] parseUsingkXML( String xml ){ ??????? try { ??????????? ByteArrayInputStream bin = ??????????????????????????? new ByteArrayInputStream( ???????????????????????????????????? xml.getBytes() ); ??????????? InputStreamReader in = new InputStreamReader( bin ); ??????????? XmlParser parser = new XmlParser( in ); ??????????? Vector??? items = new Vector(); ??????????? ??????????? parsekXMLItems( parser, items ); ??????????? ??????????? String[] tmp = new String[ items.size() ]; ??????????? items.copyInto( tmp ); ??????????? return tmp; ??????? } ??????? catch( IOException e ){ ??????????? return new String[]{ e.toString() }; ??????? } ??? } ??? ??? private void parsekXMLItems( XmlParser parser, Vector items ) ???????????????????????????????????? throws IOException { ??????? boolean inItem = false; ??????? ??????? while( true ){ ??????????? ParseEvent event = parser.read(); ??????????? switch( event.getType() ){ ??????????????? case Xml.START_TAG: ??????????????????? if( event.getName().equals( "item" ) ){ ??????????????????????? inItem = true; ??????????????????? } ??????????????????? break; ??????????????? case Xml.END_TAG: ??????????????????? if( event.getName().equals( "item" ) ){ ??????????????????????? inItem = false; ??????????????????? } ??????????????????? break; ??????????????? case Xml.TEXT: ??????????????????? if( inItem ){ ??????????????????????? items.addElement( event.getText() ); ??????????????????? } ??????????????????? break; ??????????????? case Xml.END_DOCUMENT: ??????????????????? return; ??????????? } ??????? } ??? } ??? ??? // Simple List UI component for displaying the list of ??? // items parsed from the XML document. ??? ??? class ItemList extends List implements CommandListener { ??? ??????? ItemList( String[] list ){ ??????????? super( "Items", IMPLICIT, list, null ); ??????????? addCommand( exitCommand ); ??????????? setCommandListener( this ); ??????? } ??????? ??????? public void commandAction( Command c, Displayable d ){ ??????????? if( c == exitCommand ){ ??????????????? exitMIDlet(); ??????????? } ??????? } ??? } } |