本文用Sax解析另一种风格 xml文件,只要注意两点 1. MyHandler 里不用重写 characters方法 、2. MyHandler中 用的preTag而不是前篇里的currentTag .
1. MyHandler 里不用重写 characters方法
因为weather.xml中是 elementNode(eg: <city data="ShenZhen, GuangDong" />) , 不是 textNode(eg: <name>刘德华</name>) ,所以不需要用characters方法来读取数据,因此不用重写此方法。
注意:若需要characters读取数据,例如前篇 sax解析xml文件实例一(注意endElement 内部最后 currentTag=null) , 要设置currentTag , 并且在endElement内最后 currentTag = null . 因为 <name>刘德华</name>共经历4步:1.startElement 2.characters 3. endElement 4.characters .其中第二步中 characters(char[] ch, int start, int length) 方法中读取的字符串 String currentValue = new String(ch, start, length) 值为"刘德华" 并且赋给student.name ,但第四步时,characters(char[] ch, int start, int length) 方法中读取的字符串 String currentValue = new String(ch, start, length) 值为 空,则若不在第三步endElement 内将currentTag = null 的话,则会在第四步 将一个空值再次赋给 student.name .造成了,“刘德华” 这个name被改写为空值 (其实第三步中已经正确赋值为 student.setName("刘德华"); ) 。解决办法:在第三步 endElement内最后 currentTag = null .
2. MyHandler中 用的preTag而不是前篇里的currentTag .
前篇内设置currentTag ,而本篇设置preTag . 看两个程序就很容易理解。关键一句话:若需要characters读取数据,则需要设置currentTag.
因为characters(char[] ch, int start, int length) 参数里没有当前解析到的节点 qName , 所以你必须知道当前String currentValue = new String(ch, start, length) 值对应哪个节点。 所以你必须知道当前访问的是哪个节点,或者说你必须知道你想在哪个节点时,取值。
3. 当一个节点有多个属性时,有两种方法取值:
例如: <people name="andy" id="88" age="50" city="hongkong" food="Franch" />
在public void startElement(String url, String localName, String qName, Attributes attributes)
{ 方法一:直接取字段
if("people".equals (qName)){
String name = attributes.getVaue("name");
String age = attributes.getVaue("age");
}
方法二:遍历attributes
for(int i=0 ; i<attributes.getLength(); i++){
String keyName = attributes.getQName(i);
String keyValue = attributes.getValue(i);
}
}
-------------------------------------------------------------------------------------------------------------------------------------------------
weather.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 深圳的天气情况 -->
<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="ShenZhen, GuangDong" />
<postal_code data="shenzhen" />
<latitude_e6 data="" />
<longitude_e6 data="" />
<forecast_date data="2011-01-08" />
<current_date_time data="2011-01-08 23:00:00 +0000" />
<unit_system data="SI" />
</forecast_information>
<current_conditions>
<condition data="多云" />
<temp_f data="53" />
<temp_c data="12" />
<humidity data="湿度: 43%" />
<icon data="/ig/images/weather/mostly_cloudy.gif" />
<wind_condition data="风向: 东北、风速:1 米/秒" />
</current_conditions>
<forecast_conditions>
<day_of_week data="周六" />
<low data="7" />
<high data="14" />
<icon data="/ig/images/weather/chance_of_rain.gif" />
<condition data="可能有雨" />
</forecast_conditions>
<forecast_conditions>
<day_of_week data="周日" />
<low data="6" />
<high data="12" />
<icon data="/ig/images/weather/chance_of_rain.gif" />
<condition data="可能有雨" />
</forecast_conditions>
<forecast_conditions>
<day_of_week data="周一" />
<low data="5" />
<high data="10" />
<icon data="/ig/images/weather/mostly_sunny.gif" />
<condition data="晴间多云" />
</forecast_conditions>
<forecast_conditions>
<day_of_week data="周二" />
<low data="4" />
<high data="8" />
<icon data="/ig/images/weather/chance_of_rain.gif" />
<condition data="可能有雨" />
</forecast_conditions>
</weather>
</xml_api_reply>
客户端java工程目录(左边), 服务器端web工程目录(右边)
客户端 Weather.java
package com.sax.data;
import java.util.List;
/*
*当前天气信息的类
*
*
* */
public class Weather {
/** 城市 * */
private String city;
/** 当天日期,格式为yyyy-mm-dd * */
private String forecase_date;
/** 当前时间 * */
private String current_date_time;
/** 现象描述 * */
private String current_condition;
/** 当前干燥程度 * */
private String current_humidity;
/** 当前图片地址 * */
private String current_image_url;
/** 风向 * */
private String current_wind;
/** 此处只能用有序的List集合,因为第一位索引表示当天的天气情况 **/
private List<Forecast> forecasts;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getForecase_date() {
return forecase_date;
}
public void setForecase_date(String forecase_date) {
this.forecase_date = forecase_date;
}
public String getCurrent_date_time() {
return current_date_time;
}
public void setCurrent_date_time(String current_date_time) {
this.current_date_time = current_date_time;
}
public String getCurrent_condition() {
return current_condition;
}
public void setCurrent_condition(String current_condition) {
this.current_condition = current_condition;
}
public String getCurrent_humidity() {
return current_humidity;
}
public void setCurrent_humidity(String current_humidity) {
this.current_humidity = current_humidity;
}
public String getCurrent_image_url() {
return current_image_url;
}
public void setCurrent_image_url(String current_image_url) {
this.current_image_url = current_image_url;
}
public String getCurrent_wind() {
return current_wind;
}
public void setCurrent_wind(String current_wind) {
this.current_wind = current_wind;
}
public List<Forecast> getForecasts() {
return forecasts;
}
public void setForecasts(List<Forecast> forecasts) {
this.forecasts = forecasts;
}
}
客户端Forecast.java
package com.sax.data;
public class Forecast {
/*
* 未来天气的类
* */
/** 星期几 * */
private String day_of_week;
/** 最低温度 * */
private String low;
/** 最高温度 * */
private String high;
/** 图片地址 * */
private String image_url;
/** 现象描述 * */
private String condition;
public String getDay_of_week() {
return day_of_week;
}
public void setDay_of_week(String day_of_week) {
this.day_of_week = day_of_week;
}
public String getLow() {
return low;
}
public void setLow(String low) {
this.low = low;
}
public String getHigh() {
return high;
}
public void setHigh(String high) {
this.high = high;
}
public String getImage_url() {
return image_url;
}
public void setImage_url(String image_url) {
this.image_url = image_url;
}
public String getCondition() {
return condition;
}
public void setCondition(String condition) {
this.condition = condition;
}
}
客户端 Myhandler.java
package com.sax.handler;
import java.util.ArrayList;
import java.util.List;
import javax.xml.namespace.QName;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import com.sax.data.Forecast;
import com.sax.data.Weather;
public class MyHandler extends DefaultHandler {
private Weather weather = null;
private Forecast forecast = null;
private List<Forecast> forecasts = null;
private String preTag = null;
private String nodeName = null; // 外界传参数的接口参数,本程序体内实际未用到
public MyHandler(String nodeName) {
this.nodeName = nodeName;
}
public Weather getWeather() {
return weather;
}
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
super.startDocument();
}
@Override
public void startElement(String url, String localName, String qName,
Attributes attributes) throws SAXException {
if ("weather".equals(qName)) {
weather = new Weather();
forecasts = new ArrayList<Forecast>();
}
if ("city".equals(qName)) {
// 若某个节点有多个属性,可用attributes.getQName(i)和attributes.getValue(i)来遍历获取
weather.setCity(attributes.getValue("data")); // 城市名
}
if ("forecast_date".equals(qName)) {
weather.setForecase_date(attributes.getValue("data")); // 当前日期
}
if ("current_date_time".equals(qName)) {
weather.setCurrent_date_time(attributes.getValue("data"));// 当前时间
}
if ("current_conditions".equals(qName)) {
/*
* 此处的标记非常重要,为下面的 今天的天气 的判断做铺垫, 因为condition节点在今天和未来预报里都有。
*/
preTag = "current_conditions";
}
if ("condition".equals(qName) && preTag.equals("current_conditions")) {
/*
* 如果是preTag="current_conditions"后"condition",则是今天的天气
*/
weather.setCurrent_condition(attributes.getValue("data"));
}
if ("humidity".equals(qName)) {
weather.setCurrent_humidity(attributes.getValue("data"));
}
if ("icon".equals(qName) && preTag.equals("current_conditions")) {
weather.setCurrent_image_url(attributes.getValue("data"));
}
if ("wind_condition".equals(qName)
&& preTag.equals("current_conditions")) {
weather.setCurrent_wind(attributes.getValue("data"));
}
if ("forecast_conditions".equals(qName)) {
forecast = new Forecast();
preTag = "forecast_conditions"; // 此处 preTag 第二次赋值,重要
}
if ("day_of_week".equals(qName) && forecast != null) {
forecast.setDay_of_week(attributes.getValue("data"));
}
if ("low".equals(qName) && forecast != null) {
forecast.setLow(attributes.getValue("data"));
}
if ("high".equals(qName) && forecast != null) {
forecast.setHigh(attributes.getValue("data"));
}
if ("icon".equals(qName) && forecast != null) {
forecast.setImage_url(attributes.getValue("data"));
}
if ("condition".equals(qName) && forecast != null) {
forecast.setCondition(attributes.getValue("data"));
}
}
@Override
public void characters(char[] arg0, int arg1, int arg2) throws SAXException {
// TODO Auto-generated method stub
super.characters(arg0, arg1, arg2);
}
@Override
public void endElement(String url, String localName, String qName)
throws SAXException {
if ("forecast_conditions".equals(qName)) {
forecasts.add(forecast);
forecast = null;
}
if ("weather".equals(qName)) {
weather.setForecasts(forecasts);
forecasts = null;
}
}
@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
super.endDocument();
}
}
客户端 HttpUtils.java
package com.sax.http;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class HttpUtils {
public HttpUtils() {
// TODO Auto-generated constructor stub
}
public static InputStream getXML(String path) {
InputStream inputStream = null;
try {
URL url = new URL(path);
if (url != null) {
HttpURLConnection httpURLConnection = (HttpURLConnection) url
.openConnection();
httpURLConnection.setConnectTimeout(3000);
httpURLConnection.setDoInput(true); // 从服务器获取数据
httpURLConnection.setRequestMethod("GET");
int responseCode = httpURLConnection.getResponseCode();
if (responseCode == 200) {
inputStream = httpURLConnection.getInputStream();
}
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return inputStream;
}
}
客户端SaxService.java
package com.sax.service;
import java.io.InputStream;
import java.util.List;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import com.sax.data.Forecast;
import com.sax.data.Weather;
import com.sax.handler.MyHandler;
public class SaxService {
private static Weather weather;
public static Weather readXML(InputStream inputStream , String nodeName){
weather = new Weather();
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser parser = spf.newSAXParser();
MyHandler handler = new MyHandler(nodeName); //本程序中 nodeName实际未用到
parser.parse(inputStream, handler);
weather = handler.getWeather();
} catch (Exception e) {
// TODO: handle exception
}
return weather;
}
}
客户端 Test.java
package com.sax.test;
import java.io.InputStream;
import java.util.List;
import com.sax.data.Forecast;
import com.sax.data.Weather;
import com.sax.http.HttpUtils;
import com.sax.service.SaxService;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
InputStream inputStream = HttpUtils.getXML("http://192.168.0.102:8080/myhttp/weather.xml");
Weather weather = SaxService.readXML(inputStream, "weather");
System.out.println("深圳今天天气预报:\n");
System.out.println("城市 :"+weather.getCity());
System.out.println("当前天气 :"+weather.getCurrent_condition());
System.out.println("当前湿度:"+weather.getCurrent_humidity());
System.out.println("当前风力 :"+weather.getCurrent_wind());
System.out.println("当前图标 :"+weather.getCurrent_image_url());
System.out.println("当前日期 :"+weather.getForecase_date());
System.out.println("当前时间 :"+weather.getCurrent_date_time());
System.out.println("-------------------------------------------");
System.out.println("\n未来几天的天气预报:\n");
List<Forecast> list = weather.getForecasts();
for (Forecast forecast : list) {
System.out.println("日期:"+forecast.getDay_of_week());
System.out.println("天气情况:"+forecast.getCondition());
System.out.println("最低温度:"+forecast.getLow());
System.out.println("最高温度:"+forecast.getHigh());
System.out.println("气象图标:"+forecast.getImage_url());
System.out.println("********************************************");
}
}
}