XmlPullParser - get data from tag with specific attributevalue

Dennie picture Dennie · Apr 24, 2014 · Viewed 7.6k times · Source

I'm currently creating a parser for an XML-file and everything works fine until I add an extra option to retrieve a link. I have several tags of the same name and I want one specific tag with a specific attribute value.

...
<artist>
    <name>Venom</name>
    <mbid>5ddddef1-fd5a-4ca8-8e89-df4adff4239b</mbid>
    <url>Venom</url>
    <image size="small">http://userserve-ak.last.fm/serve/34/35628151.png</image>
    <image size="medium">http://userserve-ak.last.fm/serve/64/35628151.png</image>
    <image size="large">http://userserve-ak.last.fm/serve/126/35628151.png</image>
    <image size="extralarge">http://userserve-ak.last.fm/serve/252/35628151.png</image>
</artist>
...

I'm fishing for the link in "extralarge".

My current code:

...
private TrackInfo readTrack(XmlPullParser parser) throws XmlPullParserException, IOException {
    parser.require(XmlPullParser.START_TAG, ns, "track");
    String artist = null;
    String artistPic = null;
    String artisMbid = null;
    String song = null;
    String album = null;
    while (parser.next() != XmlPullParser.END_TAG) {
        if (parser.getEventType() != XmlPullParser.START_TAG) {
            continue;
        }
        String name = parser.getName();
        if (name.equals("artist")) {

            parser.require(XmlPullParser.START_TAG, ns, "artist");
            while (parser.next() != XmlPullParser.END_TAG) {
                if (parser.getEventType() != XmlPullParser.START_TAG) {
                    continue;
                }
                String artistName = parser.getName();
                if (artistName.equals("name")) {
                    artist = readArtist(parser);
                } else if (artistName.equals("mbid")) {
                    artisMbid = readArtistMbid(parser);
                } else if (artistName.equals("image")) {
                    artistPic = readArtistPic(parser);
                } else {
                    skip(parser);
                }
            }
        } else if (name.equals("name")) {
            song = readSong(parser);
        } else if (name.equals("album")) {
            album = readAlbum(parser);
        } else {
            skip(parser);
        }
    }
    return new TrackInfo(artist, artistPic, artisMbid, song, album);
}

...

private String readArtistPic(XmlPullParser parser) throws XmlPullParserException, IOException {
    String artistPic = "";
    parser.require(XmlPullParser.START_TAG, ns, "image");
    String tag = parser.getName();
    String relType = parser.getAttributeValue(null, "size");
    if (tag.equals("image")) {
        if (relType.equals("extralarge")) {
            artistPic = readText(parser);
            parser.nextTag();
        }
    }
    parser.require(XmlPullParser.END_TAG, ns, "image");

    return artistPic;
}

...

private String readText(XmlPullParser parser) throws XmlPullParserException, IOException {
    String result = "";
    if (parser.next() == XmlPullParser.TEXT) {
        result = parser.getText();
        parser.nextTag();
    }
    return result;
}
...

The error:

E/CurrentTrackFragment logging﹕ XmlPullParserException: org.xmlpull.v1.XmlPullParserException: expected: END_TAG {null}image (position:START_TAG <image size='small'>@10:29 in java.io.InputStreamReader@52a3a014)

Anybody any idea how to handle this?

Solution!

I started working with the example Raghunandan gave me. In the end I only simplified my code and added the 'check = true' he suggested.

private TrackInfo readTrack(XmlPullParser parser) throws XmlPullParserException, IOException {
    parser.require(XmlPullParser.START_TAG, ns, "track");
    boolean nowPlaying = false;
    String artist = null;
    String artistPic = null;
    String artistMbid = null;
    String song = null;
    String songUrl = null;
    String album = null;
    String albumPic = null;
    int playedUts = 0;
    while (parser.next() != XmlPullParser.END_TAG) {
        if (parser.getEventType() != XmlPullParser.START_TAG) {
            continue;
        }
        String name = parser.getName();
        if (name.equals("artist")) {
            parser.require(XmlPullParser.START_TAG, ns, "artist");
            while (parser.next() != XmlPullParser.END_TAG) {
                if (parser.getEventType() != XmlPullParser.START_TAG) {
                    continue;
                }
                String artistName = parser.getName();
                if (artistName.equals("name")) {
                    artist = readArtist(parser);
                } else if (artistName.equals("mbid")) {
                    artistMbid = readArtistMbid(parser);
                } else if (artistName.equals("image")) {
                    boolean check = false;
                    String imagesize = parser.getAttributeValue(null, "size");
                    if (imagesize.equals("extralarge")) {
                        check = true;
                    }
                    if (check) {
                        artistPic = readArtistPic(parser);
                    } else {
                        parser.nextText();
                    }
                } else {
                    skip(parser);
                }
            }
        } else if (name.equals("name")) {
            song = readSong(parser);
        } else if (name.equals("url")) {
            songUrl = readSongUrl(parser);
        } else if (name.equals("album")) {
            album = readAlbum(parser);
        } else if (name.equals("date")) {
            playedUts = Integer.parseInt(readUts(parser));
        } else {
            skip(parser);
        }
    }
    return new TrackInfo(nowPlaying, artist, artistPic, artistMbid, song, songUrl,
            album, albumPic, playedUts);
}

...

private String readArtistPic(XmlPullParser parser) throws XmlPullParserException, IOException {
    parser.require(XmlPullParser.START_TAG, ns, "image");
    String artistPic = readText(parser);
    parser.require(XmlPullParser.END_TAG, ns, "image");
    return artistPic;
}

...

Answer

Raghunandan picture Raghunandan · Apr 24, 2014

Without the full stacktrace its hard to point the mistake. However the below works.

 public class XMLPullParserHandler {

    private String text;

    public XMLPullParserHandler() {

    }
    public Void parse(InputStream is) { // pas the input stream
        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) {
                String tagname = parser.getName();
                switch (eventType) {
                case XmlPullParser.START_TAG:
                    if (tagname.equalsIgnoreCase("image")) {

                        if(parser.getAttributeValue(null, "size").equals("extralarge"))
                        {
                            check=true;
                        }

                    }


                    break;

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

                case XmlPullParser.END_TAG:
                          String val = null; 
                         if  (tagname.equalsIgnoreCase("name")) {

                             val=text;
                             Log.i(""," name is "+val);

                         } 
                         else if (tagname.equalsIgnoreCase("mbid")) 
                         {

                             val=text;
                             Log.i(""," mbid is "+val);

                          } 
                         else if (tagname.equalsIgnoreCase("url")) 
                         {

                             val=text;
                             Log.i(""," url is "+val);

                          } 
                         else if (tagname.equalsIgnoreCase("image")) 
                         {

                             val=text;
                             if(check == true)
                             Log.i(""," image is "+val);

                          } 

                    break;

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

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

        return null;
    }
}

The log

04-24 04:39:06.906: I/(1539):  name is Venom
04-24 04:39:06.906: I/(1539):  mbid is 5ddddef1-fd5a-4ca8-8e89-df4adff4239b
04-24 04:39:06.916: I/(1539):  url is Venom
04-24 04:39:06.916: I/(1539):  name is http://userserve-ak.last.fm/serve/252/35628151.png

Alternative Solution :

private TrackInfo readTrack(XmlPullParser parser) throws XmlPullParserException, IOException {
    parser.require(XmlPullParser.START_TAG, ns, "track");
    boolean nowPlaying = false;
    String artist = null;
    String artistPic = null;
    String artistMbid = null;
    String song = null;
    String songUrl = null;
    String album = null;
    String albumPic = null;
    int playedUts = 0;
    while (parser.next() != XmlPullParser.END_TAG) {
        if (parser.getEventType() != XmlPullParser.START_TAG) {
            continue;
        }
        String name = parser.getName();
        if (name.equals("artist")) {
            parser.require(XmlPullParser.START_TAG, ns, "artist");
            while (parser.next() != XmlPullParser.END_TAG) {
                if (parser.getEventType() != XmlPullParser.START_TAG) {
                    continue;
                }
                String artistName = parser.getName();
                if (artistName.equals("name")) {
                    artist = readArtist(parser);
                } else if (artistName.equals("mbid")) {
                    artistMbid = readArtistMbid(parser);
                } else if (artistName.equals("image")) {
                    boolean check = false;
                    String imagesize = parser.getAttributeValue(null, "size");
                    if (imagesize.equals("extralarge")) {
                        check = true;
                    }
                    if (check) {
                        artistPic = readArtistPic(parser);
                    } else {
                        parser.nextText();
                    }
                } else {
                    skip(parser);
                }
            }
        } else if (name.equals("name")) {
            song = readSong(parser);
        } else if (name.equals("url")) {
            songUrl = readSongUrl(parser);
        } else if (name.equals("album")) {
            album = readAlbum(parser);
        } else if (name.equals("date")) {
            playedUts = Integer.parseInt(readUts(parser));
        } else {
            skip(parser);
        }
    }
    return new TrackInfo(nowPlaying, artist, artistPic, artistMbid, song, songUrl,
            album, albumPic, playedUts);
}

...

private String readArtistPic(XmlPullParser parser) throws XmlPullParserException, IOException {
    parser.require(XmlPullParser.START_TAG, ns, "image");
    String artistPic = readText(parser);
    parser.require(XmlPullParser.END_TAG, ns, "image");
    return artistPic;
}

...