Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Android學習指南之三十一:Android中使用SAX和pull方式解析XML

Android學習指南之三十一:Android中使用SAX和pull方式解析XML

編輯:關於android開發

       Android系統中解析XML通常使用三種方法,分別是SAX、pull和DOM。這三種方法各有優缺點。本文將在一個簡單的Google天氣預報實例的基礎上,來講解如何使用SAX和pull方式解析XML文件。

       一、Google天氣預報API簡介

       我們上一講的時候使用過Google Weather API,這裡要說明的是Google Weather API 並不是官方提供的,是非公開的API,你可以拿來用,但是不能保證准確和及時。

       首先我們可以根據經緯度來獲取天氣信息。

       http://www.google.com/ig/api?hl=zh-cn&ie=utf-8&weather=,,,34720001,113650001

       上面網址查詢的結果如下所示:

XML/HTML代碼
  1. <?xml version="1.0"?>  
  2. <XML_API_REPLY version="1">  
  3.     <WEATHER module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0">  
  4.         <FORECAST_INFORMATION>  
  5.             <CITY data="" />  
  6. <POSTAL_CODE data="" />  
  7.             <LATITUDE_E6 data="34720001" />  
  8.             <LONGITUDE_E6 data="113650001" />  
  9.             <FORECAST_DATE data="2011-03-08" />  
  10.             <CURRENT_DATE_TIME data="2011-03-08 14:00:00 +0000" />  
  11.             <UNIT_SYSTEM data="SI" />  
  12.         </FORECAST_INFORMATION>  
  13.         <CURRENT_CONDITIONS>  
  14.             <CONDITION data="晴" />  
  15.             <TEMP_F data="" />  
  16.             <TEMP_C data="" />  
  17.             <HUMIDITY data="濕度: 61%" />  
  18.             <ICON data="/ig/images/weather/sunny.gif" />  
  19.             <WIND_CONDITION data="風向: 北、風速:0 米/秒" />  
  20.         </CURRENT_CONDITIONS>  
  21.         <FORECAST_CONDITIONS>  
  22.             <DAY_OF_WEEK data="周二" />  
  23.             <LOW data="3" />  
  24.             <HIGH data="16" />  
  25.             <ICON data="/ig/images/weather/sunny.gif" />  
  26.             <CONDITION data="晴" />  
  27.         </FORECAST_CONDITIONS>  
  28.         <FORECAST_CONDITIONS>  
  29.             <DAY_OF_WEEK data="周三" />  
  30.             <LOW data="2" />  
  31.             <HIGH data="12" />  
  32.             <ICON data="/ig/images/weather/cn_cloudy.gif" />  
  33.             <CONDITION data="多雲" />  
  34.         </FORECAST_CONDITIONS>  
  35.         <FORECAST_CONDITIONS>  
  36.             <DAY_OF_WEEK data="周四" />  
  37.             <LOW data="2" />  
  38.             <HIGH data="15" />  
  39.             <ICON data="/ig/images/weather/sunny.gif" />  
  40.             <CONDITION data="晴" />  
  41.         </FORECAST_CONDITIONS>  
  42.     </WEATHER>  
  43. </XML_API_REPLY>  

       其次我們可以根據城市名稱的漢語拼音來獲取天氣信息。

       http://www.google.com/ig/api?hl=zh-cn&ie=utf-8&weather=zhengzhou

       上面網址的查詢結果如下所示:

XML/HTML代碼
  1. <?xml version="1.0"?>  
  2. <XML_API_REPLY version="1">  
  3.     <WEATHER module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0">  
  4.         <FORECAST_INFORMATION>  
  5.             <CITY data="Zhengzhou, Henan" />  
  6. <POSTAL_CODE data="zhengzhou" />  
  7.             <LATITUDE_E6 data="" />  
  8.             <LONGITUDE_E6 data="" />  
  9.             <FORECAST_DATE data="2011-03-08" />  
  10.             <CURRENT_DATE_TIME data="2011-03-08 16:00:00 +0000" />  
  11.             <UNIT_SYSTEM data="SI" />  
  12.         </FORECAST_INFORMATION>  
  13.         <CURRENT_CONDITIONS>  
  14.             <CONDITION data="霧霾" />  
  15.             <TEMP_F data="50" />  
  16.             <TEMP_C data="10" />  
  17.             <HUMIDITY data="濕度: 43%" />  
  18.             <ICON data="/ig/images/weather/haze.gif" />  
  19.             <WIND_CONDITION data="風向: 北、風速:2 米/秒" />  
  20.         </CURRENT_CONDITIONS>  
  21.         <FORECAST_CONDITIONS>  
  22.             <DAY_OF_WEEK data="周二" />  
  23.             <LOW data="4" />  
  24.             <HIGH data="14" />  
  25.             <ICON data="/ig/images/weather/mostly_sunny.gif" />  
  26.             <CONDITION data="晴間多雲" />  
  27.         </FORECAST_CONDITIONS>  
  28.         <FORECAST_CONDITIONS>  
  29.             <DAY_OF_WEEK data="周三" />  
  30.             <LOW data="1" />  
  31.             <HIGH data="11" />  
  32.             <ICON data="/ig/images/weather/sunny.gif" />  
  33.             <CONDITION data="晴" />  
  34.         </FORECAST_CONDITIONS>  
  35.         <FORECAST_CONDITIONS>  
  36.             <DAY_OF_WEEK data="周四" />  
  37.             <LOW data="3" />  
  38.             <HIGH data="15" />  
  39.             <ICON data="/ig/images/weather/sunny.gif" />  
  40.             <CONDITION data="晴" />  
  41.         </FORECAST_CONDITIONS>  
  42.         <FORECAST_CONDITIONS>  
  43.             <DAY_OF_WEEK data="周五" />  
  44.             <LOW data="7" />  
  45.             <HIGH data="19" />  
  46.             <ICON data="/ig/images/weather/mostly_sunny.gif" />  
  47.             <CONDITION data="以晴為主" />  
  48.         </FORECAST_CONDITIONS>  
  49.     </WEATHER>  
  50. </XML_API_REPLY>  

       順便說一下,我們通過 http://www.google.com/ig/cities?output=xml&hl=zh-cn&country=cn 查到鄭州的經緯度是(經度113650001,緯度34720001),那麼也就是說通過查詢經度113650001,緯度34720001處的天氣和查找鄭州的天氣應該是一致的了,實際上你也看到了,上面兩次查詢的結果並不相同。好在我們出於學習目的這點小誤差不是我們考慮的問題。

       簡單分析一下上述XML文件,會發現第二個forecast_conditions標簽裡面就是我們需要的明日天氣預報信息,包括有最高、最低氣溫、天氣情況描述和天氣描述圖片。

       二、使用SAX解析Google Weather

       DOM解析在Android開發裡一般是不被推薦的,因為DOM需要把整個XML文件都讀到內存裡,才能組裝成一個樹形結構,雖然這樣的樹形結構我們用起來很舒服,可是它的內存開銷在很多時候是難以承受的。

       而SAX(Simple API for XML)則提供了一種基於事件的處理思路,他不需要裝載、遍歷整個XML文件,只要發現你所關心的標簽或者數據,就可以隨時停止解析。這在資源比較緊缺的智能手機領域裡,還是顯得非常有價值的。廢話不說,我們還是用一個例子來展示如何使用SAX來解析XML文件,我會同樣把講解寫在文檔的注釋裡。如果同學們看著還是辛苦的話,建議找些SAX的相關知識先期補習一下。

       1、新建一個項目 Lesson31_XmlSaxParser。

       2、在MainActivit.java的代碼如下:

Java代碼
  1. package basic.android.xml.sax;   
  2.   
  3. import android.app.Activity;   
  4. import android.os.Bundle;   
  5. import android.view.View;   
  6. import android.widget.Button;   
  7. import android.widget.TextView;   
  8.   
  9. public class MainActivity extends Activity {   
  10.   
  11.     @Override  
  12.     public void onCreate(Bundle savedInstanceState) {   
  13.         super.onCreate(savedInstanceState);   
  14.         setContentView(R.layout.main);   
  15.   
  16.         //定義UI組件   
  17.         Button b1 = (Button) findViewById(R.id.button1);   
  18.         final TextView tv1 = (TextView) findViewById(R.id.textView1);   
  19.   
  20.         //為按鈕綁定監聽器   
  21.         b1.setOnClickListener(new View.OnClickListener() {   
  22.             @Override  
  23.             public void onClick(View arg0) {   
  24.                 //定義一個查詢Google天氣的字符串,後面的經緯度我寫死成鄭州的坐標了,你懂的   
  25.                 String googleWeatherUrl = "http://www.google.com/ig/api?hl=zh-cn&ie=utf-8&weather=,,,34720001,113650001";   
  26.                 //定義了一個HttpClientConnector工具類用來把google天氣預報返回的XML信息存儲在一個字符串裡,這裡可能會有聰明的同學說,你已經把整個xml都讀回來了,還扯什麼讀一半就可以退出的話,這裡要說明的是google Weather API很蛋疼,直接用sax解析會出錯,所以只能先完整讀回來   
  27.                 String googleWeatherString = HttpClientConnector.getStringByUrl(googleWeatherUrl);   
  28.                 //定義一個SAX Parse對象把xml的字符串解析成我們要的 明日天氣信息Bean   
  29.                 TomorrowWeatherVO tomorrowWeatherVO = TomorrowWeatherParse.parse(googleWeatherString);   
  30.                 //顯示天氣信息   
  31.                 if(tomorrowWeatherVO!=null){   
  32.                     tv1.setText("明日天氣情況:" + tomorrowWeatherVO.getCondition() + " 最高氣溫:" + tomorrowWeatherVO.getHigh()   
  33.                             + " 最低氣溫:" + tomorrowWeatherVO.getLow());   
  34.                 }   
  35.             }   
  36.         });   
  37.     }   
  38.   
  39. }  

       3、上面使用的HttpClientConnector工具類代碼如下:

Java代碼
  1. package basic.android.xml.sax;   
  2.   
  3. import org.apache.http.client.ResponseHandler;   
  4. import org.apache.http.client.methods.HttpGet;   
  5. import org.apache.http.impl.client.BasicResponseHandler;   
  6. import org.apache.http.impl.client.DefaultHttpClient;   
  7.   
  8. import android.util.Log;   
  9.   
  10. public class HttpClientConnector {   
  11.   
  12.     static String getStringByUrl(String url) {   
  13.   
  14.         String outputString = "";   
  15.   
  16.         // DefaultHttpClient   
  17.         DefaultHttpClient httpclient = new DefaultHttpClient();   
  18.         // HttpGet   
  19.         HttpGet httpget = new HttpGet(url);   
  20.         // ResponseHandler   
  21.         ResponseHandler<STRING> responseHandler = new BasicResponseHandler();   
  22.   
  23.         try {   
  24.             outputString = httpclient.execute(httpget, responseHandler);   
  25.             Log.i("yao", "連接成功");   
  26.         } catch (Exception e) {   
  27.             Log.i("yao", "連接失敗");   
  28.             e.printStackTrace();   
  29.         }   
  30.         httpclient.getConnectionManager().shutdown();   
  31.         return outputString;   
  32.   
  33.     }   
  34.   
  35. }</STRING>  

       4、SAX解析器 TomorrowWeatherParse.java的代碼如下:

Java代碼
  1. package basic.android.xml.sax;   
  2.   
  3. import java.io.IOException;   
  4. import java.io.StringReader;   
  5.   
  6. import javax.xml.parsers.ParserConfigurationException;   
  7. import javax.xml.parsers.SAXParserFactory;   
  8.   
  9. import org.xml.sax.InputSource;   
  10. import org.xml.sax.SAXException;   
  11. import org.xml.sax.XMLReader;   
  12.   
  13. public class TomorrowWeatherParse {   
  14.   
  15.     // 解析天氣預報字符串成一個天氣信息對象   
  16.     public static TomorrowWeatherVO parse(String googleWeatherString) {   
  17.   
  18.         SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();   
  19.   
  20.         TomorrowWeatherVO tomorrowWeatherVO = new TomorrowWeatherVO();   
  21.   
  22.         try {   
  23.             XMLReader xmlReader = saxParserFactory.newSAXParser().getXMLReader();   
  24.             WeatherXMLHandler handler = new WeatherXMLHandler(tomorrowWeatherVO);   
  25.             xmlReader.setContentHandler(handler);   
  26.   
  27.             xmlReader.parse(new InputSource(new StringReader(googleWeatherString)));   
  28.   
  29.         } catch (SAXException e) {   
  30.             e.printStackTrace();   
  31.         } catch (ParserConfigurationException e) {   
  32.             e.printStackTrace();   
  33.         } catch (IOException e) {   
  34.             e.printStackTrace();   
  35.         }   
  36.   
  37.         return tomorrowWeatherVO;   
  38.   
  39.     }   
  40.   
  41. }  

       5、TomorrowWeatherParse.java 中使用到的內容處理器 WeatherXMLHandler.java的代碼如下:

Java代碼
  1. package basic.android.xml.sax;   
  2.   
  3. import org.xml.sax.Attributes;   
  4. import org.xml.sax.SAXException;   
  5. import org.xml.sax.helpers.DefaultHandler;   
  6. import android.util.Log;   
  7.   
  8. public class WeatherXMLHandler extends DefaultHandler {   
  9.   
  10.     // 明日天氣預報Bean   
  11.     TomorrowWeatherVO tomorrowWeatherVO;   
  12.   
  13.     // 記錄出現次數   
  14.     int findCount = 0;   
  15.   
  16.     // 默認構造方法   
  17.     public WeatherXMLHandler() {   
  18.         super();   
  19.     }   
  20.   
  21.     // 構造方法   
  22.     public WeatherXMLHandler(TomorrowWeatherVO tomorrowWeatherVO) {   
  23.         this.tomorrowWeatherVO = tomorrowWeatherVO;   
  24.     }   
  25.   
  26.     /*  
  27.      * 文檔結束時觸發  
  28.      */  
  29.     @Override  
  30.     public void endDocument() throws SAXException {   
  31.         Log.i("yao", "文檔解析結束");   
  32.         super.endDocument();   
  33.     }   
  34.   
  35.     /*  
  36.      * 文檔開始時觸發  
  37.      */  
  38.     @Override  
  39.     public void startDocument() throws SAXException {   
  40.         Log.i("yao", "文檔解析開始");   
  41.         super.startDocument();   
  42.     }   
  43.   
  44.     /*  
  45.      * 元素開始時觸發  
  46.      */  
  47.     @Override  
  48.     public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {   
  49.         Log.i("yao", qName);   
  50.         if (qName.equals("forecast_conditions")) {   
  51.             findCount++;   
  52.         }   
  53.         Log.i("yao", "" + findCount);   
  54.         if (findCount == 2) {   
  55.             if (qName.equals("low")) {   
  56.                 tomorrowWeatherVO.setLow(attributes.getValue("data"));   
  57.             }   
  58.             if (qName.equals("high")) {   
  59.                 tomorrowWeatherVO.setHigh(attributes.getValue("data"));   
  60.             }   
  61.             if (qName.equals("icon")) {   
  62.                 tomorrowWeatherVO.setIcon(attributes.getValue("data"));   
  63.             }   
  64.             if (qName.equals("condition")) {   
  65.                 tomorrowWeatherVO.setCondition(attributes.getValue("data"));   
  66.             }   
  67.         }   
  68.         super.startElement(uri, localName, qName, attributes);   
  69.     }   
  70.   
  71.     /*  
  72.      * 元素結束時觸發  
  73.      */  
  74.     @Override  
  75.     public void endElement(String uri, String localName, String qName) throws SAXException {   
  76.         Log.i("yao", "元素解析結束");   
  77.         super.endElement(uri, localName, qName);   
  78.     }   
  79.   
  80.     /*  
  81.      * 讀取元素內容  
  82.      */  
  83.     @Override  
  84.     public void characters(char[] ch, int start, int length) throws SAXException {   
  85.         super.characters(ch, start, length);   
  86.     }   
  87.   
  88. }  

       上面的代碼裡有好多空方法,是為了讓你了解默認的內容處理器DefaultHandler中的常用方法,其中因為google天氣xml的特殊結構,讓我們沒有機會使用一個更常用的方法characters,很是遺憾,大家自己找資料學習吧。

       6、最後還有一個,存儲明日天氣信息的Bean:TomorrowWeatherVO.java。

Java代碼
  1. package basic.android.xml.sax;   
  2.   
  3. public class TomorrowWeatherVO {   
  4.   
  5.     String low;   
  6.     String high;   
  7.     String icon;   
  8.     String condition;   
  9.   
  10.     public String getLow() {   
  11.         return low;   
  12.     }   
  13.     public void setLow(String low) {   
  14.         this.low = low;   
  15.     }   
  16.     public String getHigh() {   
  17.         return high;   
  18.     }   
  19.     public void setHigh(String high) {   
  20.         this.high = high;   
  21.     }   
  22.     public String getIcon() {   
  23.         return icon;   
  24.     }   
  25.     public void setIcon(String icon) {   
  26.         this.icon = icon;   
  27.     }   
  28.     public String getCondition() {   
  29.         return condition;   
  30.     }   
  31.     public void setCondition(String condition) {   
  32.         this.condition = condition;   
  33.     }   
  34.   
  35.     public TomorrowWeatherVO(String low, String high, String icon,   
  36.             String condition) {   
  37.         super();   
  38.         this.low = low;   
  39.         this.high = high;   
  40.         this.icon = icon;   
  41.         this.condition = condition;   
  42.     }   
  43.   
  44.     public TomorrowWeatherVO() {   
  45.   
  46.     }   
  47. }  

       7、照例還是把簡陋的布局文件貼出來main.xml。

XML/HTML代碼
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LINEARLAYOUT xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">  
  3.     <BUTTON type=submit android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="獲取明天天氣情況" android:id="@+id/button1">  
  4.     </BUTTON>  
  5.     <TEXTVIEW android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" android:id="@+id/textView1">  
  6.     </TEXTVIEW>  
  7. </LINEARLAYOUT>  

       8、最後不要忘了在AndroidManifest.xml中加入訪問互聯網的權限:

XML/HTML代碼
  1. <USES android:name="android.permission.INTERNET" -permission></USES>  

       好,我們可以編譯並運行程序,查看結果了:

Android中使用SAX和pull方式解析XML

       點擊按鈕:

Android中使用SAX和pull方式解析XML

       OK,我們發現和QQ的天氣預報信息還是滿切合的,是不是有那麼一點點成就感?

QQ天氣預報

       三、使用pull解析Google Weather

       pull解析XML的方式和SAX比較相近,它的官網是 http://www.xmlpull.org/ ,Android中集成了pull解析方式,因此你不必自己找支持庫文件。廢話不說我們直接上實例。

       1、新建一個項目 Lesson31_XmlPullParser。

       2、重用上面項目的大部分內容,只在解析上替換一下,因此我就把解析器代碼貼出來就可以了,TomorrowWeatherPullParse.java的代碼如下:

Java代碼
  1. package basic.android.lesson31;   
  2.   
  3. import java.io.IOException;   
  4. import java.io.StringReader;   
  5.   
  6. import org.xmlpull.v1.XmlPullParser;   
  7. import org.xmlpull.v1.XmlPullParserException;   
  8. import org.xmlpull.v1.XmlPullParserFactory;   
  9.   
  10. import android.util.Log;   
  11.   
  12. public class TomorrowWeatherPullParse {   
  13.   
  14.     // 解析天氣預報字符串成一個天氣信息對象   
  15.     public static TomorrowWeatherVO parse(String googleWeatherString) {   
  16.   
  17.         Log.i("yao", "TomorrowWeatherPullParse.parse");   
  18.   
  19.         // 記錄出現次數   
  20.         int findCount = 0;   
  21.   
  22.         // 明日天氣預報Bean   
  23.         TomorrowWeatherVO tomorrowWeatherVO = new TomorrowWeatherVO();   
  24.   
  25.         try {   
  26.   
  27.             //定義工廠 XmlPullParserFactory   
  28.             XmlPullParserFactory factory = XmlPullParserFactory.newInstance();   
  29.   
  30.             //定義解析器 XmlPullParser   
  31.             XmlPullParser parser = factory.newPullParser();   
  32.   
  33.             //獲取xml輸入數據   
  34.             parser.setInput(new StringReader(googleWeatherString));   
  35.   
  36.             //開始解析事件   
  37.             int eventType = parser.getEventType();   
  38.   
  39.             //處理事件,不碰到文檔結束就一直處理   
  40.             while (eventType != XmlPullParser.END_DOCUMENT) {   
  41.                 //因為定義了一堆靜態常量,所以這裡可以用switch   
  42.                 switch (eventType) {   
  43.                 case XmlPullParser.START_DOCUMENT:   
  44.                     break;   
  45.   
  46.                 case XmlPullParser.START_TAG:   
  47.                     //給當前標簽起個名字   
  48.                     String tagName = parser.getName();   
  49.                     //看到感興趣的標簽個計數   
  50.                     if (tagName.equals("forecast_conditions")) {   
  51.                         findCount++;   
  52.                     }   
  53.                     //看到要處理的標簽,就處理   
  54.                     if (findCount == 2) {   
  55.                         if (tagName.equals("low")) {   
  56.                             //XML中的屬性可以用下面的方法獲取,其中0是序號,代表第一個屬性   
  57.                             tomorrowWeatherVO.setLow(parser.getAttributeValue(0));   
  58.                         }   
  59.                         if (tagName.equals("high")) {   
  60.                             tomorrowWeatherVO.setHigh(parser.getAttributeValue(0));   
  61.                         }   
  62.                         if (tagName.equals("icon")) {   
  63.                             tomorrowWeatherVO.setIcon(parser.getAttributeValue(0));   
  64.                         }   
  65.                         if (tagName.equals("condition")) {   
  66.                             Log.i("yao", "condition=" + parser.getAttributeValue(0));   
  67.                             tomorrowWeatherVO.setCondition(parser.getAttributeValue(0));   
  68.                         }   
  69.                     }   
  70.                     break;   
  71.                 case XmlPullParser.END_TAG:   
  72.                     break;   
  73.                 case XmlPullParser.END_DOCUMENT:   
  74.                     break;   
  75.                 }   
  76.   
  77.                 //別忘了用next方法處理下一個事件,忘了的結果就成死循環#_#   
  78.                 eventType = parser.next();   
  79.             }   
  80.   
  81.         } catch (XmlPullParserException e) {   
  82.             e.printStackTrace();   
  83.         } catch (IOException e) {   
  84.             e.printStackTrace();   
  85.         }   
  86.   
  87.         return tomorrowWeatherVO;   
  88.     }   
  89. }  

      因為編譯和運行結果與二中的完全相同,這裡就不貼圖了。

      經過總結我們知道,用pull方式解析XML文件的代碼更簡潔,也更直接方便些,最直觀的是可以少用一個Handler文件。

      本節內容就是這些了,希望大家在看完本節教程後,能夠熟練的使用SAX和pull方式解析XML文件。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved