博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
在Android中解析XML
阅读量:5757 次
发布时间:2019-06-18

本文共 13664 字,大约阅读时间需要 45 分钟。

本讲内容:使用 SAX 和 pull 解析器解析XML

(说明:本讲写的比较晚所以采用了Android2.3.3版本,其他的也一样,我会尽量在课件里使用最新版本的API。)

在Android中解析XML常用的有三种方法:SAX、DOM 和 pull ,三种方法各有优劣。本讲将用一个google天气预报的实例来和大家一起学习如何使用SAX和pull的方式XML解析。

一、Google天气预报API介绍

我们上一讲的时候使用过Google Weather API,这里要说明的是Google Weather API 并不是官方提供的,是非公开的API,你可以拿来用,但是不能保证准确和及时。

首先我们可以根据经纬度来获取天气信息。

上面网址查询的结果如下所示:

 
01 <?xml version="1.0"?>
02 <XML_API_REPLY version="1">
03     <WEATHER module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0">
04         <FORECAST_INFORMATION>
05             <CITY data="" />
06 <POSTAL_CODE data="" />
07             <LATITUDE_E6 data="34720001" />
08             <LONGITUDE_E6 data="113650001" />
09             <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>

其次我们可以根据城市名称的汉语拼音来获取天气信息。

上面网址的查询结果如下所示:

 
01 <?xml version="1.0"?>
02 <XML_API_REPLY version="1">
03     <WEATHER module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0">
04         <FORECAST_INFORMATION>
05             <CITY data="Zhengzhou, Henan" />
06 <POSTAL_CODE data="zhengzhou" />
07             <LATITUDE_E6 data="" />
08             <LONGITUDE_E6 data="" />
09             <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的代码如下:

 
01 package basic.android.xml.sax;
02   
03 import android.app.Activity;
04 import android.os.Bundle;
05 import android.view.View;
06 import android.widget.Button;
07 import android.widget.TextView;
08   
09 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 = ",,,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工具类代码如下:

 
01 package basic.android.xml.sax;
02   
03 import org.apache.http.client.ResponseHandler;
04 import org.apache.http.client.methods.HttpGet;
05 import org.apache.http.impl.client.BasicResponseHandler;
06 import org.apache.http.impl.client.DefaultHttpClient;
07   
08 import android.util.Log;
09   
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的代码如下:

 
01 package basic.android.xml.sax;
02   
03 import java.io.IOException;
04 import java.io.StringReader;
05   
06 import javax.xml.parsers.ParserConfigurationException;
07 import javax.xml.parsers.SAXParserFactory;
08   
09 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的代码如下:

 
01 package basic.android.xml.sax;
02   
03 import org.xml.sax.Attributes;
04 import org.xml.sax.SAXException;
05 import org.xml.sax.helpers.DefaultHandler;
06 import android.util.Log;
07   
08 public class WeatherXMLHandler extends DefaultHandler {
09   
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

 
01 package basic.android.xml.sax;
02   
03 public class TomorrowWeatherVO {
04   
05     String low;
06     String high;
07     String icon;
08     String condition;
09   
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

 
1 <?xml version="1.0" encoding="utf-8"?>
2 <LINEARLAYOUT xmlns: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中加入 访问互联网的权限:

 
1 <USES android:name="android.permission.INTERNET" -permission></USES>

好,我们可以编译并运行程序,查看结果了:

点击按钮:

OK,我们发现和QQ的天气预报信息还是满切合的,是不是有那么一点点成就感?

 

三、使用pull解析Google Weather

pull解析XML的方式和SAX比较相近,它的官网是 ,Android中集成了pull解析方式,因此你不必自己找支持库文件。废话不说我们直接上实例。

1、新建一个项目 Lesson31_XmlPullParser

2、重用上面项目的大部分内容,只在解析上替换一下,因此我就把解析器代码贴出来就可以了,TomorrowWeatherPullParse.java的代码如下:

 
01 package basic.android.lesson31;
02   
03 import java.io.IOException;
04 import java.io.StringReader;
05   
06 import org.xmlpull.v1.XmlPullParser;
07 import org.xmlpull.v1.XmlPullParserException;
08 import org.xmlpull.v1.XmlPullParserFactory;
09   
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解析方式更简单直接些,代码也少一些,至少省了一个handler文件,不是吗。好了本讲就到这里,祝愉快。

转载于:https://www.cnblogs.com/ou10209019/archive/2012/07/28/2613660.html

你可能感兴趣的文章
菊子曰获取模板的草稿{29C28FD771BA4B0D8693}
查看>>
png图片在ie不透明的解决方案
查看>>
hibernate的各种保存方式的区别 (save,persist,update,saveOrUpdte,merge,flush,lock)等
查看>>
Linux运维学习笔记之二:常用命令3
查看>>
Oracle loadjava 命令报ORA-06550错误
查看>>
String args[]
查看>>
人生十大效应
查看>>
山西灵石公安执法为何这么难
查看>>
嵌入式学习参考网站
查看>>
python的学习之旅
查看>>
利用发射进行对象赋值
查看>>
检测用户输入是否合法
查看>>
log4j为指定包或者类输出单独的日志
查看>>
我的友情链接
查看>>
回忆淡了
查看>>
javaScript之正则
查看>>
vsftpd配置详解
查看>>
打地鼠游戏ios源码
查看>>
Python 学习笔记 - 反射
查看>>
mysql错误
查看>>