SAX 解析Google Weather API的问题

[size=medium]
这几天在研究使用SAX方式来解析XML文件,在这个期间还没有遇到什么阻塞性的问题,也看到大家在使用Google Weather API来实现天气预报数据显示的功能,所以我也写了一个,总体来说没有大的问题,但是遇到一个很奇怪的问题,如果直接使用URL.openStream()方法获得的InputStream解析老是出问题,问题的提示很奇怪,如果把文件保存起来,再解析就没有什么问题,不知道什么问题,希望大家热心帮助,初步感觉是字符编码问题。
[/size]

com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: Invalid byte 2 of 2-byte UTF-8 sequence.
at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.invalidByte(UTF8Reader.java:684)
at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.read(UTF8Reader.java:369)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(XMLEntityScanner.java:1742)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.scanLiteral(XMLEntityScanner.java:1064)
at com.sun.org.apache.xerces.internal.impl.XMLScanner.scanAttributeValue(XMLScanner.java:813)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanAttribute(XMLDocumentFragmentScannerImpl.java:1539)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1316)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2747)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:807)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
at WeatherForecast.parse(WeatherForecast.java:51)
at WeatherForecast.parse(WeatherForecast.java:30)
at WeatherForecast.main(WeatherForecast.java:65)
null


import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

public class WeatherForecast {
public final static String WEATHER_URL =
"http://www.google.com/ig/api?weather=%s&hl=zh_CN";

public static WeatherSet parse(String city) {
city = city.replace(" ", "%20");
String weatherURL = String.format(WEATHER_URL, city);
InputStream in = null;
try {
URL url = new URL(weatherURL);
in = url.openStream();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return parse(in);
}

public static WeatherSet parse(String fileName, String city) {
InputStream in = WeatherForecast.class.getResourceAsStream(fileName);
return parse(in);
}

public static WeatherSet parse(InputStream in) {
if(in == null){
return null;
}
SAXParserFactory spf = SAXParserFactory.newInstance();

try {
SAXParser parser = spf.newSAXParser();

XMLReader reader = parser.getXMLReader();
GoogleWeatherHandler handler = new GoogleWeatherHandler();
reader.setContentHandler(handler);

reader.parse(new InputSource(in));
return handler.getWeatherSet();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

public static void main(String[] args) {
WeatherForecast weather = new WeatherForecast();
WeatherSet weatherSet = weather.parse("api.xml","beijing,china");
System.out.println(weatherSet);
}
}


public class WeatherForecastCondition extends WeatherCondition {
private String low;

private String high;

private String dayOfWeek;

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 getDayOfWeek() {
return dayOfWeek;
}

public void setDayOfWeek(String dayOfWeek) {
this.dayOfWeek = dayOfWeek;
}

@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("\t<day_of_week data=" + this.dayOfWeek +"/>\n");
sb.append("\t<low data=" + this.low+"/>\n");
sb.append("\t<high data=" + this.high+"/>\n");
sb.append("\t<icon data=" +super.getIcon()+"/>\n");
sb.append("\t<condition data=" +super.getCondition()+"/>\n");
return sb.toString();
}
}


import java.util.ArrayList;
import java.util.List;

public class WeatherSet {
private String city;

private String postalCode;

private String latitude;

private String longitude;

private String forecastDate;

private String currentDate;

private String unitSystem;

private WeatherCurrentCondition currentCondition;

private List<WeatherForecastCondition> forecastConditions;

public WeatherSet() {
forecastConditions = new ArrayList<WeatherForecastCondition>();
}

public WeatherForecastCondition getLastForecastCondition() {
return forecastConditions.get(forecastConditions.size() - 1);
}

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}

public String getPostalCode() {
return postalCode;
}

public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}

public String getLatitude() {
return latitude;
}

public void setLatitude(String latitude) {
this.latitude = latitude;
}

public String getLongitude() {
return longitude;
}

public void setLongitude(String longitude) {
this.longitude = longitude;
}

public String getForecastDate() {
return forecastDate;
}

public void setForecastDate(String forecastDate) {
this.forecastDate = forecastDate;
}

public String getCurrentDate() {
return currentDate;
}

public void setCurrentDate(String currentDate) {
this.currentDate = currentDate;
}

public String getUnitSystem() {
return unitSystem;
}

public void setUnitSystem(String unitSystem) {
this.unitSystem = unitSystem;
}

public WeatherCurrentCondition getCurrentCondition() {
return currentCondition;
}

public void setCurrentCondition(WeatherCurrentCondition currentCondition) {
this.currentCondition = currentCondition;
}

public List<WeatherForecastCondition> getForeastConditions() {
return forecastConditions;
}

public void setForeastConditions(
List<WeatherForecastCondition> foreastConditions) {
this.forecastConditions = foreastConditions;
}

@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("<city data=" + this.city + "/>\n");

sb.append("<postal_code data=" +this.postalCode+"/>\n");
sb.append("<latitude_e6 data=" +this.latitude+"/>\n");
sb.append("<longitude_e6 data="+this.longitude+"/>\n");
sb.append("<forecast_date data="+this.forecastDate+"/>\n");
sb.append("<current_date_time data="+this.currentDate+"/>\n");
sb.append("<unit_system data="+this.unitSystem+"/>\n");

sb.append("\n\n" + this.currentCondition + "\n\n");
sb.append(this.forecastConditions);

return sb.toString();
}
}


public class WeatherCurrentCondition extends WeatherCondition {
private String tempFahrenheit;

private String tempCelcius;

private String humidity;

private String icon;

private String windCondition;

public String getTempFahrenheit() {
return tempFahrenheit;
}

public void setTempFahrenheit(String tempFahrenheit) {
this.tempFahrenheit = tempFahrenheit;
}

public String getTempCelcius() {
return tempCelcius;
}

public void setTempCelcius(String tempCelcius) {
this.tempCelcius = tempCelcius;
}

public String getHumidity() {
return humidity;
}

public void setHumidity(String humidity) {
this.humidity = humidity;
}

public String getIcon() {
return icon;
}

public void setIcon(String icon) {
this.icon = icon;
}

public String getWindCondition() {
return windCondition;
}

public void setWindCondition(String windCondition) {
this.windCondition = windCondition;
}

@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("<condition data=" + super.getCondition() + "/>\n");
sb.append("<temp_f data=" + this.tempFahrenheit + "/>\n");
sb.append("<temp_c data=" + this.tempFahrenheit + "/>\n");
sb.append("<humidity data=humidity:" + this.humidity + "12%/>\n");
sb.append("<icon data=" + super.getIcon() +"/>\n");
sb.append("<wind_condition data=" + this.windCondition +"/>\n");
return sb.toString();
}
}


public class WeatherCondition {
private String condition;


private String icon;

public String getCondition() {
return condition;
}

public void setCondition(String condition) {
this.condition = condition;
}

public String getIcon() {
return icon;
}

public void setIcon(String icon) {
this.icon = icon;
}
}


import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class GoogleWeatherHandler extends DefaultHandler {
private WeatherSet weatherSet = null;

private boolean inForecastInformation = false;
private boolean inCurrentConditions = false;
private boolean inForecastConditions = false;

public WeatherSet getWeatherSet() {
return weatherSet;
}

public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if(qName.equals("xml_api_reply") || qName.equals("weather")) {
return;
}
if(qName.equals("forecast_information")){
weatherSet = new WeatherSet();
inForecastInformation = true;
return;
}

if(qName.equals("current_conditions")){
WeatherCurrentCondition todayCondition = new WeatherCurrentCondition();
weatherSet.setCurrentCondition(todayCondition);
inCurrentConditions = true;
return;
}

if(qName.equals("forecast_conditions")){
WeatherForecastCondition forecastCondition = new WeatherForecastCondition();
weatherSet.getForeastConditions().add(forecastCondition);
inForecastConditions = true;
return;
}

String dataAttr = attributes.getValue("data");

if(inForecastInformation) {
if(qName.equals("city")){
weatherSet.setCity(dataAttr);
} else if(qName.equals("postal_code")){
weatherSet.setPostalCode(dataAttr);
} else if(qName.equals("latitude_e6")){
weatherSet.setLatitude(dataAttr);
} else if(qName.equals("longitude_e6")) {
weatherSet.setLongitude(dataAttr);
} else if(qName.equals("forecast_date")){
weatherSet.setForecastDate(dataAttr);
} else if(qName.equals("current_date_time")){
weatherSet.setCurrentDate(dataAttr);
} else if(qName.equals("unit_system")){
weatherSet.setUnitSystem(dataAttr);
}
return;
}

if(qName.equals("condition")) {
if(inCurrentConditions) {
weatherSet.getCurrentCondition().setCondition(dataAttr);
} else {
weatherSet.getLastForecastCondition().setCondition(dataAttr);
}
} else if(qName.equals("temp_f")) {
weatherSet.getCurrentCondition().setTempFahrenheit(dataAttr);
} else if(qName.equals("temp_c")){
weatherSet.getCurrentCondition().setTempCelcius(dataAttr);
} else if(qName.equals("humidity")){
weatherSet.getCurrentCondition().setHumidity(dataAttr);
} else if(qName.equals("icon")){
if(inCurrentConditions) {
weatherSet.getCurrentCondition().setIcon(dataAttr);
} else {
weatherSet.getLastForecastCondition().setIcon(dataAttr);
}
} else if(qName.equals("wind_condition")){
weatherSet.getCurrentCondition().setWindCondition(dataAttr);
} else if(qName.equals("day_of_week")) {
weatherSet.getLastForecastCondition().setDayOfWeek(dataAttr);
} else if(qName.equals("low")) {
weatherSet.getLastForecastCondition().setLow(dataAttr);
} else if(qName.equals("high")) {
weatherSet.getLastForecastCondition().setHigh(dataAttr);
}
}

@Override
public void endElement(String uri, String localName, String name)
throws SAXException {
if(name.equals("forecast_information")){
inForecastInformation = false;
return;
}

if(name.equals("current_conditions")){
inCurrentConditions = false;
return;
}

if(name.equals("forecast_conditions")){
inForecastConditions = false;
return;
}
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值