android學習二十二(使用SAX解析xml)

來源:互聯網
上載者:User

標籤:android   sax   xml   pull   

          上一篇部落格是使用Pull解析xml檔案的,Pull解析方式雖然非常好用,但它並不是我們唯一的選擇。SAX解析也是一種特別常用的XML解析方式,雖然它的用法比Pull解析複雜,但在語義方面會更加的清楚。

        通常情況下我們都會建立一個類繼承自DefaultHandler,並重寫父類的五個方法,如下所示:

package com.jack.networktest;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;public class MyHandler extends DefaultHandler {@Overridepublic void characters(char[] ch, int start, int length)throws SAXException {// TODO Auto-generated method stubsuper.characters(ch, start, length);}@Overridepublic void endDocument() throws SAXException {// TODO Auto-generated method stubsuper.endDocument();}@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {// TODO Auto-generated method stubsuper.endElement(uri, localName, qName);}@Overridepublic void startDocument() throws SAXException {// TODO Auto-generated method stubsuper.startDocument();}@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {// TODO Auto-generated method stubsuper.startElement(uri, localName, qName, attributes);}}


       startDocument()方法會在開始xml解析的時候調用,startElement方法會在開始解析某個節點的時候調用,
 characters方法會在擷取節點中內容的時候調用,endElement方法會在完成解析某個結點的時候調用,endDocument()方法會在完成xml解析的時候調用。其中,startElement, characters和endElement這三個方法是有參數的,從xml中解析出的資料就會以參數的形式傳入到這些方法中。需要注意的是,在擷取結點中內容時,characters方法可能會被調用多次,一些分行符號也被當作內容解析出來,我們需要針對這種情況在代碼中做好控制。
        那麼下面就讓我們嘗試調用SAX解析的方式來實現和前面部落格同樣的功能。建立一個ContentHandler類繼承自
   DefaultHandler,並重寫父類的五個方法,如下所示: 

package com.jack.networktest;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;import android.util.Log;public class ContentHandler extends DefaultHandler {private String nodeName;private StringBuilder id;private StringBuilder name;private StringBuilder version;@Overridepublic void characters(char[] ch, int start, int length)throws SAXException {// TODO Auto-generated method stub//super.characters(ch, start, length);//根據當前的結點名判斷將內容添加到哪一個StringBuilder對象中if("id".equals(nodeName)){id.append(ch,start,length);//Log.d("ContentHandler", "id.append(ch,start,length); "+id.toString().trim());}else if("name".equals(nodeName)){name.append(ch,start,length);}else if("version".equals(nodeName)){version.append(ch,start,length);}}@Overridepublic void endDocument() throws SAXException {// TODO Auto-generated method stub//super.endDocument();}@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {// TODO Auto-generated method stub//super.endElement(uri, localName, qName);if("app".equals(localName)){Log.d("ContentHandler", "id is "+id.toString().trim());Log.d("ContentHandler", "name is "+name.toString().trim());Log.d("ContentHandler", "version is "+version.toString().trim());//最後要將StringBuilder清空掉id.setLength(0);name.setLength(0);version.setLength(0);//Log.d("ContentHandler", "app app app app =  "+nodeName);}//Log.d("ContentHandler", "endElement  ="+localName);}@Overridepublic void startDocument() throws SAXException {// TODO Auto-generated method stub//super.startDocument();id=new StringBuilder();name=new StringBuilder();version=new StringBuilder();}@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {// TODO Auto-generated method stub//super.startElement(uri, localName, qName, attributes);nodeName = localName;//記錄當前節點名//Log.d("ContentHandler", "startElement localname= "+localName);}}

我們首先給id,name和version結點分別定義了一個StringBuilder對象,並在startDocument方法裡對
它們進行了初始化。每當開始解析某個結點的時候,startElement方法就會得到調用,其中localName參數記錄著當前
結點的名字,這裡我們把它記錄下來。接著在解析結點中具體內容的時候就會調用characters方法,我們會根據當前結點名進行判斷,將解析出的內容添加到哪一個StringBuilder對象中。最後在endElement方法中進行判斷,如果app結點已經解析完成,就列印出id,name和version的內容。需要注意的是,目前id,name和version中都可能是包括斷行符號或分行符號的,因此在我們列印之前我們還需要調用一下trim()方法,並且列印完成後還要將StringBuilder的內容清空掉,不然的話會影響下一次內容的讀取。
接下來的工作就是修改MainActivity中的代碼,如下所示:

package com.jack.networktest;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.StringReader;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import javax.xml.parsers.SAXParserFactory;import org.apache.http.HttpEntity;import org.apache.http.HttpHost;import org.apache.http.HttpRequest;import org.apache.http.HttpResponse;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.HttpClient;import org.apache.http.client.ResponseHandler;import org.apache.http.client.methods.HttpGet;import org.apache.http.client.methods.HttpUriRequest;import org.apache.http.conn.ClientConnectionManager;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.params.HttpParams;import org.apache.http.protocol.HttpContext;import org.apache.http.util.EntityUtils;import org.xml.sax.InputSource;import org.xml.sax.XMLReader;import org.xmlpull.v1.XmlPullParser;import org.xmlpull.v1.XmlPullParserFactory;import android.annotation.SuppressLint;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.Menu;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;public class MainActivity extends Activity implements OnClickListener{public static final int SHOW_RESPONSE=0;private Button sendRequest=null;private TextView responseText=null;private Handler handler=new Handler(){@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubsuper.handleMessage(msg);switch(msg.what){case SHOW_RESPONSE:String response=(String) msg.obj;//在這裡進行UI操作,將結果顯示到介面上responseText.setText(response);break;default:break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);sendRequest=(Button) findViewById(R.id.send_request);responseText=(TextView) findViewById(R.id.response_text);sendRequest.setOnClickListener(this);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}@Overridepublic void onClick(View v) {// TODO Auto-generated method stubif(v.getId()==R.id.send_request){//sendRequestWithHttpURLConnection();sendRequestWithHttpClient();}}private void sendRequestWithHttpURLConnection(){//開啟線程來發起網路請求new Thread(new Runnable(){@Overridepublic void run() {// TODO Auto-generated method stubHttpURLConnection connection=null;try {URL url=new URL("http://www.baidu.com");connection =(HttpURLConnection) url.openConnection();connection.setRequestMethod("GET");connection.setConnectTimeout(8000);connection.setReadTimeout(8000);InputStream in=connection.getInputStream();//下面對擷取到的輸入資料流進行讀取BufferedReader reader=new BufferedReader(new InputStreamReader(in));StringBuilder response=new StringBuilder();String line;while((line=reader.readLine())!=null){response.append(line);}Message message=new Message();message.what=SHOW_RESPONSE;//將伺服器返回的結果存放到Message中message.obj=response.toString();handler.sendMessage(message);} catch (MalformedURLException e) {// TODO Auto-generated catch blocke.printStackTrace();}catch(Exception e){e.printStackTrace();}finally{if(connection!=null){connection.disconnect();}}}}).start();}private void sendRequestWithHttpClient(){new Thread(new Runnable(){@Overridepublic void run() {// TODO Auto-generated method stubtry{HttpClient httpClient=new DefaultHttpClient() ;//HttpGet httpGet=new HttpGet("http://www.baidu.com");//指定訪問的伺服器位址是電腦本機,10.0.2.2對模擬器來說就是電腦原生ip地址//8080為連接埠號碼HttpGet httpGet=new HttpGet("http://10.0.2.2:8080/get_data.xml");HttpResponse httpResponse=httpClient.execute(httpGet);if(httpResponse.getStatusLine().getStatusCode()==200){//請求和響應都成功了HttpEntity entity=httpResponse.getEntity();String response=EntityUtils.toString(entity,"utf-8");//調用parseXMLWithPull方法解析伺服器返回的資料//parseXMLWithPull(response);//調用parseXMLWithSAX方法解析伺服器返回的資料parseXMLWithSAX(response);Message message=new Message();message.what=SHOW_RESPONSE;//將伺服器返回的結果存放到Message中message.obj=response.toString();handler.sendMessage(message);}}catch(Exception e){e.printStackTrace();}}}).start();}//使用Pull解析xmlprivate void parseXMLWithPull(String xmlData){//Log.d("MainActivity", "parseXMLWithPull(String xmlData)");try{//擷取到XmlPullParserFactory的執行個體,並藉助這個執行個體得到XmlPullParser對象XmlPullParserFactory factory=XmlPullParserFactory.newInstance();XmlPullParser xmlPullParser=factory.newPullParser();//調用XmlPullParser的setInput方法將伺服器返回的xml資料設定進去開始解析xmlPullParser.setInput(new StringReader(xmlData));//通過getEventType()方法得到當前解析事件int eventType=xmlPullParser.getEventType();String id="";String name="";String version="";while(eventType!=XmlPullParser.END_DOCUMENT){//通過getName()方法得到當前節點的名字,如果發現節點名等於id、name、或version//就調用nextText()方法來擷取結點具體的內容,每當解析完一個app結點就將擷取到的內容列印出來String nodeName=xmlPullParser.getName();//Log.d("MainActivity",""+eventType+ " nodeName= "+nodeName);switch(eventType){//開始解析某個節點case XmlPullParser.START_TAG:{if("id".equals(nodeName)){id=xmlPullParser.nextText();}else if("name".equals(nodeName)){name=xmlPullParser.nextText();}else if("version".equals(nodeName)){version=xmlPullParser.nextText();}break;}case XmlPullParser.END_TAG:{if("app".equals(nodeName)){Log.d("MainActivity", "id is "+id);Log.d("MainActivity", "name is "+name);Log.d("MainActivity", "version is "+version);}break;}default:break;}//調用next()方法擷取到下一個解析事件eventType=xmlPullParser.next();}}catch(Exception e){e.printStackTrace();}}//進行SAX解析的函數private void parseXMLWithSAX(String xmlData){/* * parseXMLWithSAX方法中先建立一個SAXParserFactory的對象,然後再擷取到 * XMLReader對象,接著將我們編寫的ContentHandler的執行個體設定到XMLReader中, * 最後調用parse()方法開始執行解析。 * */try{SAXParserFactory factory=SAXParserFactory.newInstance();XMLReader xmlReader=factory.newSAXParser().getXMLReader();ContentHandler handler=new ContentHandler();//將ContentHandler的執行個體設定到XMLReader中xmlReader.setContentHandler(handler);//開始執行解析xmlReader.parse(new InputSource(new StringReader(xmlData)));}catch(Exception e){e.printStackTrace();}}}

現在重新運行一下程式,點擊send request按鈕,觀察列印的日誌如下所示:




到這裡SAX解析xml就結束,xml還有一種dom的解析方式,也可以用來解析xml。



http://blog.csdn.net/j903829182/article/details/42499209


android學習二十二(使用SAX解析xml)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.