如何通过SAXParser类解析调用 Google Weather API接口返回的XML结果

环境:SDK1.1

内容:

调用Google Weather API

通过WEB 下载数据

通过SAXParser 解析XML 文件(数据流)

创建自定义界面(继承LinearLayout

难度3.5/5

笔者用2小时写代码,其中半个小时是用于xml-layout,这再次显示了Android-Platform平台的强大和灵活

问题/ 疑难:

结果:

Screenshot taken with SDK-version m3:
clip_image001 clip_image002

 

描述

在这个教程中,我们将使用Google (iGoogle ) Weather API 我们将简单地调用如下样式的URL

引用:

// Style:
http://www.google.com/ig/api?weather=QUERY
// Working Examples ( Note : that " "(space) has to be replaced with its html-expression "%20 "
// Your browser manages that conversion automatically )
http://www.google.com/ig/api?weather=Schriesheim,Germany
http://www.google.com/ig/api?weather=New%20York,%20USA

这里使用google weather API三种调用方法中的第三种,使用城市名称法

扩展说明 :(译者)

Google Weather API 调用说明

1.邮政编码法:(支持美国地区)

http://www.google.com/ig/api?hl=zh-cn&weather=94043
(94043 为 山景城, 美国加州 的邮政编码)
2.经纬度坐标作法:

http://www.google.com/ig/api?hl=zh-cn&weather=,,,30670000,104019996
(30670000,104019996 为 成都, 中国大陆 的经纬度坐标)

3.城市名称法:

http://www.google.com/ig/api?weather=Beijing

当查询的城市能找到时,返回的数据样式如下:

XML:

<xml_api_reply version="1">
     <weather module_id="0" tab_id="0">
          <forecast_information>
               <!-- Some inner tags containing data about the city found, time and unit-stuff -->
               <city data="Schriesheim, BW"/>
               <postal_code data="Schriesheim,Germany"/>
               <latitude_e6 data=""/>
               <longitude_e6 data=""/>
               <forecast_date data="2007-12-21"/>
               <current_date_time data="2007-12-21 19:50:00 +0000"/>
               <unit_system data="US"/>
          </forecast_information>
          <current_conditions>
               <!-- Some inner tags containing data of current weather -->
               <condition data="Fog"/>
               <temp_f data="23"/>
               <temp_c data="-5"/>
               <humidity data="Humidity: 93%"/>
               <icon data="/images/weather/fog.gif"/>
               <wind_condition data="Wind: N at 1 mph"/>
          </current_conditions>
          <forecast_conditions>
               <!-- Some inner tags containing data about future weather -->
               <day_of_week data="Today"/>
               <low data="24"/>
               <high data="37"/>
               <icon data="/images/weather/fog.gif"/>
               <condition data="Fog"/>
          </forecast_conditions>
          <forecast_conditions>
               <!-- Some inner tags containing data about future weather -->
               <day_of_week data="Sat"/>
               <low data="24"/>
               <high data="37"/>
               <icon data="/images/weather/sunny.gif"/>
               <condition data="Clear"/>
          </forecast_conditions>
          <forecast_conditions>
               <!-- Another set as above -->
          </forecast_conditions>
          <forecast_conditions>
               <!-- Another set as above -->
          </forecast_conditions>
     </weather>
</xml_api_reply>

如果你访问的城市不存在时,例如:

http://www.google.com/ig/api?weather=FantasyTown,Disneyland

它将返回一个提示错误的XML,格式如下:

XML:

<xml_api_reply version="1">
     <weather module_id="0" tab_id="0">
          <problem_cause data=""/>
     </weather>
</xml_api_reply>

1)由于我们需要解析返回的XML信息,因此我们需要选择一个XML解析工具(XML-parse)

我(原作者)决定选择使用SAX-Parser,SAX 是因简单易用的XML-API 而著称.所以它正合适我们使用。(注:参看相关资料)

 

通过解析转换,它可以把weather api 返回的XML 数据转成如下的对象:

Java:

public class WeatherSet {
     // ===========================================================
     // Fields
     // ===========================================================
     private WeatherCurrentCondition myCurrentCondition = null;
     private ArrayList<WeatherForecastCondition> myForecastConditions =
          new ArrayList<WeatherForecastCondition>(4);
     // ===========================================================
     // Getter & Setter
     // ===========================================================
     // Getter & Setter for fields above...
}

它包括了两个子成员 WeatherCurrentCondition ,WeatherForecastInfoSet

WeatherCurrentCondition 包含了XML 数据中current_conditions 节点的标签

WeatherForecastInfoSet 包含了XML 数据中forecast_conditions 节点的标签

关于XML 解析部分就在这里结束了,其它信息可以看实际代码。

 

2)让我们看一下它的布局,这个布局相对以前我们做的来说会更复杂些。下面是它的关系

clip_image004

我使用如些多的tablelayouts,是因为tablelayout能更容易伸展它的子视窗。

使用小图标表示天气,使用文本显示温度,他们共同组成自定义视图(SingleWeatherInfoView ),它继承于LinearLayout,如下图

clip_image006

通过继承LinearLayout,我们得到设置android:orientation -Attribute to ="horizontal" 或是"vertical "的属性。你可以出图片的功能,在视图中心的图片SingleWeatherInfoView 是当天的天气。在这下面的四个图片SingleWeatherInfoView 依次显示的是之后四天的天气。在此又一次的显示了面向对象编程的是最好的。

如何创建自定义视图,可以查看实际代码。

3 )到此90%的工作已经完成,最后的事情是把他们组合起来,我们使用提交按钮的OnClickListener 监听事件,当点击后,发生如下事情:

l 从输入框中取出用户所输入的数据当成调成google weather api

l 创建一个SAXParserXML 解析对象,解析调用google weather api 后返回的数据

l 显示天气预报信息,包括当天和之后四天的天气。

添加如下代码:

And this is the corresponding code:

Java:

          Button cmd_submit = (Button)findViewById(R.id.cmd_submit);
          cmd_submit.setOnClickListener(new OnClickListener(){
               @Override
               public void onClick(View arg0) {
                    URL url;
                    try {
                         /* Get what user typed to the EditText. */                       
                         String cityParamString =
                              ((EditText)findViewById(R.id.edit_input))
                                   .getText().toString();
                         String queryString =
                              "http://www.google.com/ig/api?weather="
                                   + cityParamString;
                         /* Replace blanks with HTML-Equivalent. */
                         url = new URL(queryString.replace(" ", "%20"));
                         /* Get a SAXParser from the SAXPArserFactory. */
                         SAXParserFactory spf = SAXParserFactory.newInstance();
                         SAXParser sp = spf.newSAXParser();
                         /* Get the XMLReader of the SAXParser we created. */
                         XMLReader xr = sp.getXMLReader();
                         /* Create a new ContentHandler and apply it to the XML-Reader*/
                         GoogleWeatherHandler gwh = new GoogleWeatherHandler();
                         xr.setContentHandler(gwh);
                         /* Parse the xml-data our URL-call returned. */
                         xr.parse(new InputSource(url.openStream()));
                         /* Our Handler now provides the parsed weather-data to us. */
                         WeatherSet ws = gwh.getWeatherSet();
                         /* Update the SingleWeatherInfoView with the parsed data. */
  updateWeatherInfoView(R.id.weather_today, ws.getWeatherCurrentCondition());
  updateWeatherInfoView(R.id.weather_1, ws.getWeatherForecastConditions().get(0));
updateWeatherInfoView(R.id.weather_2, ws.getWeatherForecastConditions().get(1));
  updateWeatherInfoView(R.id.weather_3, ws.getWeatherForecastConditions().get(2));
  updateWeatherInfoView(R.id.weather_4, ws.getWeatherForecastConditions().get(3));
                    } catch (Exception e) {
                         resetWeatherInfoViews();
                         Log.e(DEBUG_TAG, "WeatherQueryError", e);
                    }
               }
          });

如何显示网络图片?

通过IE访问:http://www.google.com/ig/images/weather/chance_of_storm.gif

clip_image008

SingleWeatherInfoView类中setWeatherIcon

新建工程把下面代码加入工程

private ImageView myWeatherImageView = null ;

@Override

public void onCreate(Bundle savedInstanceState) {

super .onCreate(savedInstanceState);

setContentView(R.layout.main );

myWeatherImageView = (ImageView)findViewById(R.id.webimg );

this .myWeatherImageView.setPadding(10, 5, 5, 5);

URL url;

try {

url = new URL("http://www.google.com/ig/images/weather/chance_of_storm.gif");

setWeatherIcon(url);

} catch (MalformedURLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

public void setWeatherIcon(URL aURL) {

try {

URLConnection conn = aURL.openConnection();

conn.connect();

InputStream is = conn.getInputStream();

BufferedInputStream bis = new BufferedInputStream(is);

Bitmap bm = BitmapFactory.decodeStream (bis);

bis.close();

is.close();

this .myWeatherImageView.setImageBitmap(bm);

}catch (Exception e){

}

}

在main.xml中添加:

<ImageView

android:id="@+id/webimg"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center"

>

</ImageView>

注意:在AndroidManifest.xml文中添加

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

才能访问网络.

运行显示:

clip_image010

工程结构:

clip_image012

WeatherForecast : 视图,程序主入口

GoogleWeatherHandler : google weather 处理器,主要是解析XML文件

WeatherSet : 是XML标签集,其中包括成员WeatherCurrentCondition,WeatherForecastCondition

SingleWeatherInfoView : 以下视图

clip_image006[1]

关于译者:

clip_image013 向上是一名C语言开发人员,现从事MTK手机开发,有三年C++,C终端开发经验。现看好android将来的发展,加到机器人大家庭,努力学习,为社区贡献力量。坚持向上人生路。

参考资料:

http://www.anddev.org/android_weather_forecast_-_google_weather_api_-_full_source-t361.html

从mapbar地图中取出来的按“城市名字,经度,纬度,

http://zhuyx808.javaeye.com/blog/327917

http://www.google.com/ig/api?hl=zh-cn&weather=94043

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值