源码下载地址:Android中,使用SAX和PULL解析天气预报XML
天气预报是大家日常生活中经常接触到的信息,现在有一天气预报信息,对其进行解析。
在Android中对XML的解析常用到两种解析技术:
SAX解析和PULL解析。
SAX支持已经内置到了JDK1.5中,无需在项目中添加任何jar文件。
Pull是Android内置的解析器(谷歌推荐使用Pull)
两种解析技术都是基于事件驱动的流式处理数据。
已经获取了某天的天气预报信息,数据如下:
weather.xml 为了读取方便,放在项目src目录下。
<?xml version="1.0" ?>
<xml_api_reply version="1">
<weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1"
row="0" section="0">
<forecast_information>
<city data="" />
<postal_code data="" />
<latitude_e6 data="34720001" />
<longitude_e6 data="113650001" />
<forecast_date data="2012-04-06" />
<current_date_time data="2012-04-06 20:00:00 +0000" />
<unit_system data="SI" />
</forecast_information>
<current_conditions>
<condition data="晴" />
<temp_f data="75" />
<temp_c data="24" />
<humidity data="湿度: 5%" />
<icon data="/ig/images/weather/sunny.gif" />
<wind_condition data="风向: 东南、风速:2 米/秒" />
</current_conditions>
<forecast_conditions>
<day_of_week data="周五" />
<low data="9" />
<high data="24" />
<icon data="/ig/images/weather/mostly_sunny.gif" />
<condition data="晴间多云" />
</forecast_conditions>
<forecast_conditions>
<day_of_week data="周六" />
<low data="10" />
<high data="25" />
<icon data="/ig/images/weather/sunny.gif" />
<condition data="晴" />
</forecast_conditions>
<forecast_conditions>
<day_of_week data="周日" />
<low data="12" />
<high data="26" />
<icon data="/ig/images/weather/mostly_sunny.gif" />
<condition data="晴间多云" />
</forecast_conditions>
<forecast_conditions>
<day_of_week data="周一" />
<low data="12" />
<high data="21" />
<icon data="/ig/images/weather/mostly_sunny.gif" />
<condition data="以晴为主" />
</forecast_conditions>
</weather>
</xml_api_reply>
CurrentWeatherInfo.java 存放当前天气情况的实体Bean
package com.feioh;
/**
* 存放当前天气情况的实体Bean
*
* @author yalin
*
*/
public class CurrentWeatherInfo {
private String content;
private String humidity;
private String wind_condition;
public CurrentWeatherInfo() {
super();
}
public CurrentWeatherInfo(String content, String humidity,
String wind_condition) {
super();
this.content = content;
this.humidity = humidity;
this.wind_condition = wind_condition;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getHumidity() {
return humidity;
}
public void setHumidity(String humidity) {
this.humidity = humidity;
}
public String getWind_condition() {
return wind_condition;
}
public void setWind_condition(String wind_condition) {
this.wind_condition = wind_condition;
}
// 重写toString(),更改实体返回信息
@Override
public String toString() {
// TODO Auto-generated method stub
return "当前天气情况:"+content + "," + humidity +","+ wind_condition + "。";
}
}
WeatherInfo.java 存放每天天气情况的实体Bean
package com.feioh;
/**
* 存放每天天气信息的实体Bean
* @author yalin
*
*/
public class WeatherInfo {
private String date;
private String high;
private String low;
private String content;
public WeatherInfo() {
super();
}
public WeatherInfo(String date, String high, String low, String content) {
super();
this.date = date;
this.high = high;
this.low = low;
this.content = content;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getHigh() {
return high;
}
public void setHigh(String high) {
this.high = high;
}
public String getLow() {
return low;
}
public void setLow(String low) {
this.low = low;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
//重写toString(),更改实体返回信息
@Override
public String toString() {
// TODO Auto-generated method stub
return date+",天气:"+content+",最高温度:"+high+"℃,最低温度:"+low+"℃。";
}
}
WeatherService.java 使用SAX技术解析xml的业务类
package com.feioh;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
/**
* 解析XML所需要的业务类
* 在这个业务类中,通过SAXParserFactory得到解析器saxParser
* @author yalin
*
*/
public class WeatherService {
public static Map<String,Object> readXML(InputStream inputStream) throws Exception
{
//创建一个解析器工厂
SAXParserFactory factory=SAXParserFactory.newInstance();
//通过工厂创建解析器
SAXParser saxParser=factory.newSAXParser();
//实例saxParser.parse()函数 所需要的Handler对象
XMLContentHandler handler=new XMLContentHandler();
//开始解析...ing
saxParser.parse(inputStream, handler);
//关闭输入流
inputStream.close();
//得到每天天气情况信息
List<WeatherInfo> re=handler.getList();
//得到当前天气情况信息
CurrentWeatherInfo currentWeatherInfo=handler.getCurrent();
//把当前天气情况 和 每天天气情况放入到Map集合中
Map<String,Object> map=new HashMap<String,Object>();
map.put("everyday", re);
map.put("current", currentWeatherInfo);
return map;
}
}
XMLContentHandler.java SAX解析所需要的Handler
package com.feioh;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* SAX技术是通过继承DefaultHandler实现对xml的解析的。 SAX读取xml时,只要提供实现ContentHandler接口的类
* DefaultHandler实现了ContentHandler接口,继承这个类,重写相应方法即可。
*
* @author yalin
*
*/
public class XMLContentHandler extends DefaultHandler {
private List<WeatherInfo> list;// 存放解析过的xml数据集
private WeatherInfo weatherInfo;// 存放解析过的xml数据对象
private CurrentWeatherInfo currentWeatherInfo;// 存放解析过的当前天气信息数据
boolean TAG = false;// 标识属于哪个标签的天气情况
// 提供一个公共方法,便于其他使用者调用
public List<WeatherInfo> getList() {
return list;
}
//提供一个公共方法,返回当前天气情况
public CurrentWeatherInfo getCurrent() {
return currentWeatherInfo;
}
// 解析到xml文档开头的时候,调用这个方法,可以在其中做一些预处理的工作
@Override
public void startDocument() throws SAXException {
// 实例list集合
list = new ArrayList<WeatherInfo>();
super.startDocument();
}
// 解析到xml文档结束的时候,调用这个方法,可以在其中做一些善后的工作
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
/**
* 当读到一个开始标签的时候,会触发这个方法
*
* localName参数代表不带命名空间前缀的标签的名称 qName参数代表带命名空间前缀的标签的名称
* attributes参数表示元素内部属性名和属性值的集合
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
// current_conditions这个元素标签
// 表示当前的天气情况
// 当解析到这个标签的时候,实例CurrentWeatherInfo
// 以便保存当前的天气情况
if ("current_conditions".equals(localName)) {
currentWeatherInfo = new CurrentWeatherInfo();
}
if (!TAG) {
// 解析到天气情况的时候
if ("condition".equals(localName)) {
// 把最天气情况放入到实体中
currentWeatherInfo.setContent(attributes.getValue("data"));
}
// 解析到空气湿度的时候
if ("humidity".equals(localName)) {
// 把空气湿度信息放入到实体中
currentWeatherInfo.setHumidity(attributes.getValue("data"));
}
// 解析到风向的时候
if ("wind_condition".equals(localName)) {
// 把风向信息放入到实体中
currentWeatherInfo.setWind_condition(attributes
.getValue("data"));
}
}
// forecast_conditions这个元素标签
// 表示一天的天气情况
// 当解析到这个标签的时候,实例WeatherInfo
// 以便保存这一天的天气情况
if ("forecast_conditions".equals(localName)) {
// 实例WeatherInfo,存放解析到的天气信息
weatherInfo = new WeatherInfo();
// 把TAG设置为true
TAG = true;
}
if (TAG) {
// 解析到日期的时候
if ("day_of_week".equals(localName)) {
// 把日期存放在实体中
weatherInfo.setDate(attributes.getValue("data"));
}
// 解析到最低温度的时候
if ("low".equals(localName)) {
// 把最低温度放入到实体中
weatherInfo.setLow(attributes.getValue("data"));
}
// 解析到最高温度的时候
if ("high".equals(localName)) {
// 把最高温度放入到实体中
weatherInfo.setHigh(attributes.getValue("data"));
}
// 解析到天气情况的时候
if ("condition".equals(localName)) {
// 把最天气情况放入到实体中
weatherInfo.setContent(attributes.getValue("data"));
}
}
super.startElement(uri, localName, qName, attributes);
}
/**
* 用于处理xml文件中读到的内容
*/
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
super.characters(ch, start, length);
}
// 解析到结束标签的时候,调用这个方法
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
// 当结束标签为forecast_conditions的时候
// 把WeatherInfo加入到list列表中,同时设置WeatherInfo为空
if ("forecast_conditions".equals(qName) && weatherInfo != null) {
list.add(weatherInfo);
weatherInfo = null;
}
super.endElement(uri, localName, qName);
}
}
PullWeatherService.java PULL技术解析xml
package com.feioh;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.SAXParserFactory;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import android.util.Xml;
/**
* 使用Pull解析XML文件
* 使用Xml.newPullParser()函数得到解析器
* 等价于工厂生成的解析器,如:
* XmlPullParserFactory factory=XmlPullParserFactory.newInstance();
* XmlPullParser parser=factory.newPullParser();
* @author yalin
*
*/
public class PullWeatherService {
public static Map<String,Object> readXML(InputStream inputStream) throws Exception
{
List<WeatherInfo> list=null;//存放解析每天天气情况集合
WeatherInfo weatherInfo=null;//存放解析每天天气
CurrentWeatherInfo currentWeatherInfo=null;//存放当前天气情况
boolean TAG = false;// 标识属于哪个标签的天气情况
//得到Pull解析器
// XmlPullParser parser=Xml.newPullParser();
XmlPullParserFactory factory=XmlPullParserFactory.newInstance();
XmlPullParser parser=factory.newPullParser();
//开始解析...ing
parser.setInput(inputStream,"UTF-8");
//获取事件的代码值
int eventCode=parser.getEventType();
//如果xml文档没有结束
while(eventCode != XmlPullParser.END_DOCUMENT)
{
switch(eventCode)
{
//当开始解析的时候,实例List集合
case XmlPullParser.START_DOCUMENT:
list=new ArrayList<WeatherInfo>();
break;
case XmlPullParser.START_TAG:
// current_conditions这个元素标签
// 表示当前的天气情况
// 当解析到这个标签的时候,实例CurrentWeatherInfo
// 以便保存当前的天气情况
if("current_conditions".equals(parser.getName()))
{
currentWeatherInfo=new CurrentWeatherInfo();
}
if(!TAG)
{
// 解析到天气情况的时候
if("condition".equals(parser.getName()))
{
// 把最天气情况放入到实体中
currentWeatherInfo.setContent(parser.getAttributeValue(0));
}
// 解析到空气湿度的时候
if("humidity".equals(parser.getName()))
{
// 把空气湿度信息放入到实体中
currentWeatherInfo.setHumidity(parser.getAttributeValue(0));
}
// 解析到风向的时候
if("wind_condition".equals(parser.getName()))
{
// 把风向信息放入到实体中
currentWeatherInfo.setWind_condition(parser.getAttributeValue(0));
}
}
// forecast_conditions这个元素标签
// 表示一天的天气情况
// 当解析到这个标签的时候,实例WeatherInfo
// 以便保存这一天的天气情况
if("forecast_conditions".equals(parser.getName()))
{
// 实例WeatherInfo,存放解析到的天气信息
weatherInfo=new WeatherInfo();
// 把TAG设置为true
TAG=true;
}
if(TAG)
{
// 解析到日期的时候
if("day_of_week".equals(parser.getName()))
{
// 把日期存放在实体中
weatherInfo.setDate(parser.getAttributeValue(0));
}
// 解析到最低温度的时候
if("low".equals(parser.getName()))
{
// 把最低温度放入到实体中
weatherInfo.setLow(parser.getAttributeValue(0));
}
// 解析到最高温度的时候
if("high".equals(parser.getName()))
{
// 把最高温度放入到实体中
weatherInfo.setHigh(parser.getAttributeValue(0));
}
// 解析到天气情况的时候
if("condition".equals(parser.getName()))
{
// 把最天气情况放入到实体中
weatherInfo.setContent(parser.getAttributeValue(0));
}
}
break;
case XmlPullParser.END_TAG:
// 当结束标签为forecast_conditions的时候
// 把WeatherInfo加入到list列表中,同时设置WeatherInfo为空
if("forecast_conditions".equals(parser.getName()) && weatherInfo !=null)
{
list.add(weatherInfo);
weatherInfo=null;
}
break;
}
//进入下一个元素
eventCode=parser.next();
}
Map<String,Object> map=new HashMap<String,Object>();
map.put("everyday",list);
map.put("current", currentWeatherInfo);
return map;
}
}
MainActivity.java 一个简陋的界面便于显示预报信息
package com.feioh;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
/** Called when the activity is first created. */
private InputStream inputStream = null;// 定义解析xml的输入流
private List<WeatherInfo> list = null;// 定义返回每天天气情况列表
private CurrentWeatherInfo current = null;// 定义当前天气情况
private TextView tv_everyday, tv_current = null;// 用来显示当前天气情况和每天天气情况
private TextView tv_everyday_pull,tv_current_pull=null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 存放天气情况的TextView
tv_everyday = (TextView) findViewById(R.id.tv_everyday);
tv_current = (TextView) findViewById(R.id.tv_current);
tv_everyday_pull = (TextView) findViewById(R.id.tv_everyday_pull);
tv_current_pull = (TextView) findViewById(R.id.tv_current_pull);
// 解析xml的事件源 按钮
Button btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(listener);
Button btn_pull=(Button) findViewById(R.id.btn_pull);
btn_pull.setOnClickListener(listener);
}
//解析XML事件
OnClickListener listener = new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
// 把要解析的xml放入输入流中
inputStream = MainActivity.class.getClassLoader().getResourceAsStream("weather.xml");
// 开始解析xml,返回Map类型数据集
if(v.getId()==R.id.btn)
{
Map<String, Object> map = WeatherService.readXML(inputStream);
// 得到每天天气情况
list = (List<WeatherInfo>) map.get("everyday");
// 得到当前天气情况
current = (CurrentWeatherInfo) map.get("current");
// 设置显示当前天气情况
tv_current.setText("");
tv_current.setText(tv_current.getText() + current.toString());
// 设置显示每天天气情况
tv_everyday.setText("");
if (list != null) {
for (WeatherInfo weather : list) {
tv_everyday.setText(tv_everyday.getText()
+ weather.toString() + "\n");
}
}
}else if(v.getId()==R.id.btn_pull)
{
Map<String, Object> map = PullWeatherService.readXML(inputStream);
// 得到每天天气情况
list = (List<WeatherInfo>) map.get("everyday");
// 得到当前天气情况
current = (CurrentWeatherInfo) map.get("current");
// 设置显示当前天气情况
tv_current_pull.setText("");
tv_current_pull.setText(tv_current_pull.getText() + current.toString());
// 设置显示每天天气情况
tv_everyday_pull.setText("");
if (list != null) {
for (WeatherInfo weather : list) {
tv_everyday_pull.setText(tv_everyday_pull.getText()
+ weather.toString() + "\n");
}
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
}
main.xml 最后贴上布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/btn"
android:text="SAX解析XML天气预报">
</Button>
<TextView android:text="" android:id="@+id/tv_current"
android:layout_width="fill_parent" android:layout_height="wrap_content">
</TextView>
<TextView android:text="" android:id="@+id/tv_everyday"
android:layout_width="fill_parent" android:layout_height="wrap_content">
</TextView>
<Button android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/btn_pull"
android:text="PULL解析XML天气预报">
</Button>
<TextView android:text="" android:id="@+id/tv_current_pull"
android:layout_width="fill_parent" android:layout_height="wrap_content">
</TextView>
<TextView android:text="" android:id="@+id/tv_everyday_pull"
android:layout_width="fill_parent" android:layout_height="wrap_content">
</TextView>
</LinearLayout>
查看效果预览: