標籤:
每個訪問網路的應用程式都有一個自己的伺服器,我們可以向伺服器提交資料,也可以從伺服器上擷取資料。那麼,這些資料是用什麼格式在網路上傳輸的呢?一般,我們會在網路上傳輸一些格式化的資料,這些資料有一定的結構和語義。另一方收到資料訊息後就可以按照相同的結構規格來進行解析,從而擷取到想要的那部分內容。
網路上傳輸資料最常用的格式有兩種,XML和JSON。下面,我們介紹通過SAX方式來解析XML。
首先,進行準備一段XML格式的資料。 get_data.xml
1 <apps> 2 <app> 3 <id></id> 4 <name>Google Maps</name> 5 <version>1.0</version> 6 </app> 7 <app> 8 <id>2</id> 9 <name>Chrome</name>10 <version>2.1</version>11 </app>12 <app>13 <id>3</id>14 <name>Google Play</name>15 <version>2.3</version>16 </app>17 </apps>
我們搭建的伺服器網址為:http://10.0.105.36/get_data.xml
接下來通過HttpURLConnection方式來擷取伺服器上的內容,代碼如下
private void sendRequestWithHttpURLConnection(){ //開啟線程來發送網路請求 new Thread(new Runnable() { @Override public void run() { HttpURLConnection connection=null; try { URL url=new URL("http://10.0.105.36/get_data.xml"); connection= (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(8000); connection.setReadTimeout(8000); //擷取輸入資料流 InputStream in=connection.getInputStream(); //對擷取到的流進行讀取 BufferedReader br=new BufferedReader(new InputStreamReader(in)); StringBuilder response=new StringBuilder(); String line; while ((line=br.readLine())!=null){ response.append(line); } parseXMLWithSAX(response.toString()); //這裡調用的是下文中parseXMLWithSAX()方法 }catch (Exception e){ e.printStackTrace(); }finally { if (connection!=null){ connection.disconnect(); } } } }).start(); }
一般情況我們會建立一個類ContentHandler繼承自DefaultHandler ,並重寫父類的五個方法 ,如下:
package com.example.NetTest21;import android.util.Log;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;/** * Created by Demon on 2015/1/18. */public class ContentHandler extends DefaultHandler { private String nodeName; private StringBuilder id; private StringBuilder name; private StringBuilder version; @Override public void startDocument() throws SAXException { id=new StringBuilder(); name=new StringBuilder(); version=new StringBuilder(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { //記錄當前結點名 nodeName=localName; } @Override public void characters(char[] ch, int start, int length) throws SAXException { //根據當前的節點名判斷將內容添加到哪一個StringBuilder對象中 if ("id".equals(nodeName)){ id.append(ch,start,length); }else if ("name".equals(nodeName)){ name.append(ch, start, length); }else if ("version".equals(nodeName)){ version.append(ch, start, length); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { 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); } } @Override public void endDocument() throws SAXException { }}
我們首先給id、name和version節點分別定義了一個StringBuilder對象,並在startDocument()方法中對它們進行了初始化。每當開始解析某個節點的時候,startElement()方法就會得到調用。其中localName參數記錄著當前結點的名字,我們將它記錄下來。接著在解析結點中具體內容的時候就會調用characters()方法,我們根據當前的結點名進行判斷,將解析出的內容添加到哪一個StringBuilder對象中。最後在endElement()方法中進行判斷,如果app結點已經解析完成,就列印出id name 和version的內容。注意,目前id、name和version中可能包括斷行符號或分行符號,因此在列印之前我們還需要調用一下trim()方法,並且列印完成後還要將StringBuilder的內容清空掉,不然會影響下一次內容的讀取。
接下來建立一個parseXMLWithSAX(String xmlData)方法 用來解析資料。
private void parseXMLWithSAX(String xmlData){ 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(); } }
parseXMLWithSAX()方法中先是建立了一個SAXParseFactory的對象,然後再擷取到XMLReader對象,接著將我們編寫的ContentHandler的執行個體設定到XMLReader中,最後調用parse()方法開始執行解析。
---------------------------------------------------------------------------
---------------------------------------------------------------------------
文章來自於郭霖大神的《第一行代碼》,轉載請註明出處。
Android中通過SAX方式解析XML