`

SAX 解析Google Weather API的问题

    博客分类:
  • java
阅读更多

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

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;
        }
    }
}




分享到:
评论
4 楼 asialee 2012-07-20  
dolphin0618 写道
我也遇到了跟你一样的情况,很奇怪

什么问题? 可以交流下
3 楼 dolphin0618 2012-07-20  
dolphin0618 写道
你别用url.openStream()了,这样写就OK
new InputSource(new BufferedReader(new InputStreamReader(con.getInputStream(),"GBK")))

要用GBK,用UTF-8还会有乱码
2 楼 dolphin0618 2012-07-20  
你别用url.openStream()了,这样写就OK
new InputSource(new BufferedReader(new InputStreamReader(con.getInputStream(),"GBK")))
1 楼 dolphin0618 2012-07-20  
我也遇到了跟你一样的情况,很奇怪

相关推荐

    android的对google天气预报的Sax解析

    SAX解析器是一种事件驱动的解析方式,它逐行读取XML文档,遇到特定的元素开始、结束或有属性时触发回调函数。这种方式相较于DOM解析器,内存占用较低,适合处理大体积的XML文档。 要开始解析Google天气预报的XML,...

    xml解析google天气预报

    总的来说,解析谷歌天气预报的XML文件需要理解XML的结构,熟悉SAX解析机制,以及掌握Android的多线程和UI更新技巧。这是一个典型的Android应用开发中的数据获取与处理任务,对提升开发者的数据处理能力和网络编程...

    android版本的天气预报

    在获取到天气API的XML响应后,开发者会使用SAX解析器来解析这些数据,提取出所需的天气信息,例如最高温度、最低温度、天气状况等,然后存储在应用程序的数据结构中。 接下来,是用户界面的设计。在Android中,通常...

    google天气预报XML-Pull解析版(完全解析)

    XML-Pull解析是一种轻量级的解析方法,与DOM(Document Object Model)和SAX(Simple API for XML)不同,它不需要一次性加载整个XML文档到内存中。XML-Pull解析器在读取XML文档时,只处理当前的事件,这样可以节省...

    Android使用GoogleWeather制作天气预报程序[定义].pdf

    Google Weather API是一种网络服务,可以向开发人员提供全球天气信息。在Android应用程序中,可以通过HTTP请求从该API获取特定地点的天气预报数据。 3. XML解析: 在本例中,Google Weather API返回的数据格式为XML...

    Android天气小部件源码

    4. **Google API的应用**:获取天气信息通常需要从网络获取数据,这里可能用到Google的开放API,如Google Weather API(虽然现在已经关闭,但可替换为其他第三方天气API)。API调用通常涉及到网络请求,如HTTP/HTTPS...

    android通过google api获取天气信息示例

    这里使用了Java的SAX解析器(Simple API for XML)。`SAXParserFactory`和`SAXParser`用于创建解析器,`XMLReader`设置内容处理器,最后通过自定义的`XmlHandler`处理XML事件。 5. **自定义处理器(`XmlHandler`)*...

    Android开发之XML文件的解析的三种方法

    假设我们在开发天气预报应用程序的时候,使用google给我们提供的API,以及天气预报数据,例如我们要获得北京当前的天气预报数据,即可在浏览器中输入如下地址:http://www.google.com/ig/api?&weather=beijing。

    Google天气实例

    【Google天气实例】是一个关于如何在Android平台上利用Google的Weather Web Service进行天气查询的示例项目。这个项目展示了如何通过网络请求获取XML格式的天气数据,并解析这些数据以展示给用户。下面将详细讲解...

    天气代码设计

    Android平台可以使用Gson库解析JSON,或者使用DOM或SAX解析XML。解析过程中要提取关键信息,如温度、湿度、风速、天气状况图标等。 3. **网络请求**:Android提供了HttpURLConnection和OkHttp等库进行网络请求。...

    android 源码 天气预报

    Gson库可以将JSON字符串直接转换为Java对象,而PullParser或SAX解析器可以处理XML数据。 4. **数据库存储**:在"DB"这个文件夹中,可能包含的是SQLite数据库的相关代码。Android内置了SQLite数据库系统,用于持久化...

    andorid天气预报.rar

    - JSON或XML数据需要解析为Java对象,Android提供了Gson库用于JSON解析,而XML可以使用内置的SAX或DOM解析器,或者使用第三方库如Jackson、XmlPullParser。 - 数据模型(Model)的设计至关重要,应与返回的数据...

    Android天气查询

    Android系统提供了多种定位服务,最常见的就是使用Google Play服务中的Fused Location Provider API。这个API能够综合使用GPS、Wi-Fi、移动网络等多种方式,提供高效且节能的定位服务。我们需要在AndroidManifest....

    天气:Android Weather App

    Android提供了Gson和Jackson库进行JSON解析,或者使用DOM/SAX/Pull解析器处理XML。 5. **本地存储**:为了在离线状态下依然能展示最近的天气信息,数据通常会被缓存到SQLite数据库或使用SharedPreferences进行轻量...

    自定义天气预报

    - JSON和XML解析:使用Gson库解析JSON数据,或者使用Java内置的SAX或DOM解析XML数据。 - 解析出的数据通常包括气温、湿度、风速、天气状况等,将这些数据存储在自定义的Java对象(如WeatherInfo类)中。 4. **...

    android_weather_forecasts

    除此之外,考虑到用户体验,应用可能还包括定位服务,使用Google Play Services的Fused Location Provider API来获取用户的当前位置,以便提供本地天气信息。另外,通知服务也可能是其中一部分,当天气条件发生变化...

Global site tag (gtag.js) - Google Analytics