2

I am trying to parse openweathermap api http://api.openweathermap.org/data/2.5/weather?q=London&mode=xml. I am using KXmlParser via XmlPullParserFactory.newPullParser() but the XMLPullParser.getName() is always returning null. It might be some silly mistake but it seems that I might need your help to see it.

Here's the code to read the api via HTTPURLConnection.

 URL url = new URL(urlString);
                URLConnection urlConnection = url.openConnection();
                HttpURLConnection httpConnection = (HttpURLConnection) urlConnection;
                httpConnection.setRequestMethod("GET");
                httpConnection.connect();
                if(httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK){
                    inputStream = httpConnection.getInputStream();
                }

I used

BufferedReader buffer = new BufferedReader(
                            new InputStreamReader(inputStream));
                    String s="";
                    while ((s=buffer.readLine())!=null){
                        stringBuffer.append(s);
                        System.out.println(s);
                    }

to make sure that I am reading the xml successfully and it turns out that the code is running properly. Next, I am using the following code parse the xml

XmlPullParserFactory xmlFactoryObject = XmlPullParserFactory.newInstance();
            XmlPullParser myparser = xmlFactoryObject.newPullParser();

            myparser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES
                    , false);
            myparser.setInput(inputStream, null);

            int event = myparser.getEventType();

            while (event != XmlPullParser.END_DOCUMENT){
                Log.d("XMLPullParserHandler", "sdfdsf " + myparser.getName());
                String name = myparser.getName();

But I am getting java.lang.NullPointerException at myparser.getName(); also the above log is showing "sdfdsf null".

What am I doing wrong?

Rohan Kandwal
  • 9,112
  • 8
  • 74
  • 107
  • you want to parse the xml or you could change the mode to json. http://api.openweathermap.org/data/2.5/weather?q=London&mode=json.and parse the json – Raghunandan Aug 18 '14 at 10:26
  • @Raghunandan I'm learning how to parse in xml, JSON is next. So, I would like to parse in xml. – Rohan Kandwal Aug 18 '14 at 10:34

2 Answers2

2

You can either parse the given xml or change the mode to json and parse the json

Your xml tag looks like

<city id="2643743" name="London"> 
// tag name is city
// id and name are attributes with values 2643743 and London

Note: I have only shown parsing of few tags. But it should help you understand and do the parsing for the rest yourself.

From the documantation

public abstract String getName () Added in API level 1

For START_TAG or END_TAG events, the (local) name of the current element is returned when namespaces are enabled. When namespace processing is disabled, the raw name is returned. For ENTITY_REF events, the entity name is returned. If the current event is not START_TAG, END_TAG, or ENTITY_REF, null is returned.

To parse xml and get values

public class XMLPullParserHandler {



    public XMLPullParserHandler() {

    }
    public Void parse(InputStream is) {
        XmlPullParserFactory factory = null;
        XmlPullParser parser = null;
        try {
            factory = XmlPullParserFactory.newInstance();
            factory.setNamespaceAware(true);
            parser = factory.newPullParser();

            parser.setInput(is, null);
            boolean check =false;

           //factory instantiates an object

            int eventType = parser.getEventType();
            while (eventType != XmlPullParser.END_DOCUMENT) {

                switch (eventType) {
                case XmlPullParser.START_TAG:

                    String tagname = parser.getName();
                    Log.i("Tag names are ",tagname);

                    if (tagname.equalsIgnoreCase("city")) {

                        if(parser.getAttributeValue(null, "id").equals("264374"))
                        {
                             String cityname= parser.getAttributeValue(null, "name");
                             Log.i(" City Name is ",cityname);
                        }

                    }
                    if (tagname.equalsIgnoreCase("coord")) {

                             String lat= parser.getAttributeValue(null, "lat");
                             String lon= parser.getAttributeValue(null, "lon");
                             Log.i("Latitude and Longitude is","Lat= "+lat+"Lon= "+lon);

                    }
                    if (tagname.equalsIgnoreCase("sun")) {

                     String rise= parser.getAttributeValue(null, "rise");
                     String set= parser.getAttributeValue(null, "set");
                     Log.i("Sun Rise and Sun set is","Rise= "+rise+"Set= "+set);

               }

                    break;

                case XmlPullParser.TEXT:
                    break;

                case XmlPullParser.END_TAG:


                    break;

                default:
                    break;
                }
                eventType = parser.next();
            }

        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }
}

The log

08-18 16:14:35.885: I/City Name is(31634): London
08-18 16:14:35.885: I/Latitude and Longitude is(31634): Lat= 51.51Lon= -0.13
08-18 16:14:35.885: I/Sun Rise and Sun set is(31634): Rise= 2014-08-18T04:51:39Set= 2014-08-18T19:16:53

Also if your xml tag looks like below

<cityname type="test">City is London</cityname> 

To get the value

case XmlPullParser.TEXT:
       text = parser.getText();
break;

case XmlPullParser.END_TAG:
       if (tagname.equalsIgnoreCase("cityname")) {                             
        Log.i("Name is",text);
       }
break;

Edit:

Asynctask

class TheTask extends AsyncTask<Void,Void,Void>
{

@Override
protected Void doInBackground(Void... params) {
    // TODO Auto-generated method stub
    String response;
       try {
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet("http://api.openweathermap.org/data/2.5/weather?q=London&mode=xml");

            HttpResponse httpResponse = httpClient.execute(httpGet);
            HttpEntity httpEntity = httpResponse.getEntity();
            response = EntityUtils.toString(httpEntity);

            InputStream is = new ByteArrayInputStream(response.getBytes(Charset.forName("UTF-8")));
            new XMLPullParserHandler().parse(is); 

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    return null;
}   
}
Raghunandan
  • 132,755
  • 26
  • 225
  • 256
  • Thanks for such detailed description but only default case is triggered once in my switch (I copied your code), which means that something is wrong with my input stream. Can you please share your HTTPURLConnection and input stream code? – Rohan Kandwal Aug 18 '14 at 11:26
  • @RohanKandwal i took the xml copied it to assests folder and parsed it from there. i will have to write the code whole code to check and will take some time – Raghunandan Aug 18 '14 at 11:36
  • @RohanKandwal check the edit. just invoke the asynctask where you need – Raghunandan Aug 18 '14 at 11:44
  • @RohanKandwal what happes now?? – Raghunandan Aug 18 '14 at 12:25
1

START_DOCUMENT is the first event you always get from a parser, while getName() returns not null only in case of START_TAG, END_TAG and ENTITY_REF events.

For START_TAG or END_TAG events, the (local) name of the current element is returned when namespaces are enabled. When namespace processing is disabled, the raw name is returned. For ENTITY_REF events, the entity name is returned. If the current event is not START_TAG, END_TAG, or ENTITY_REF, null is returned.

Try this:

while (event != XmlPullParser.END_DOCUMENT) {
    if (event == XmlPullParser.START_TAG || event == XmlPullParser.END_TAG) {
        Log.d("XMLPullParserHandler", "sdfdsf " + myparser.getName());
        String name = myparser.getName();
    }
    event = myparser.next();
}