本文用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,length) 值为 空,则若不在第三步endElement 内将currentTag = null 的话,则会在第四步 将一个空值再次赋给 student.name .造成了,“刘德华”这个name被改写为空值 (其实第三步中已经正确赋值为 student.setName("刘德华"); ) 。解决办法:在第三步 endElement内最后 currentTag = null .
2.MyHandler中 用的preTag而不是前篇里的currentTag .
前篇内设置currentTag,而本篇设置preTag . 看两个程序就很容易理解。关键一句话:若需要characters读取数据,则需要设置currentTag.
因为characters(char[] ch,int length) 参数里没有当前解析到的节点 qName,所以你必须知道当前String currentValue = new String(ch,length) 值对应哪个节点。所以你必须知道当前访问的是哪个节点,或者说你必须知道你想在哪个节点时,取值。
例如: <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");
Stringage = 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,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 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("********************************************"); } } }