0

I'm having trouble parsing some xml tags. I'm very new to Android development and I'm still struggling with basics.

I'm sorry if this post is sort of hard to read.

I want to read the following XML file that I download:

    <lfm status="ok">
    <album>
        <name>Now, Diabolical</name>
        <artist>Satyricon</artist>
        <mbid>28d51e3f-b12c-4948-b35b-c1f5aae76ed2</mbid>
        <image size="">...</image>
        <listeners>131741</listeners>
        <playcount>2876007</playcount>
        <tracks>
            <track rank="1">
                <name>Now, Diabolical</name>
                <url>...</url>
                <duration>367</duration>
                <streamable fulltrack="0">0</streamable>
                <artist>
                    <name>Satyricon</name>
                    <mbid>8eed05a5-e9a1-4dda-8b33-e354c4ecc8b6</mbid>
                    <url>https://www.last.fm/music/Satyricon</url>
                </artist>
            </track>
            <track rank="2">
                <name>K.I.N.G.</name>
                <url>https://www.last.fm/music/Satyricon/_/K.I.N.G.</url>
                <duration>216</duration>
                <streamable fulltrack="0">0</streamable>
                <artist>
                    <name>Satyricon</name>
                    <mbid>8eed05a5-e9a1-4dda-8b33-e354c4ecc8b6</mbid>
                    <url>https://www.last.fm/music/Satyricon</url>
                </artist>
            </track>
        </tracks>
        <tags>
            <tag>
                <name>black metal</name>
                <url>https://www.last.fm/tag/black+metal</url>
            </tag>
            <tag>...</tag>
            <tag>...</tag>
        </tags>
    </album>
</lfm>

I read it with my XmlPullParser class:

try {
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            XmlPullParser xpp = factory.newPullParser();

            FileInputStream fis = ctx.openFileInput("AlbumInfo.xml");

            BufferedReader reader = new BufferedReader(new InputStreamReader(fis));

            xpp.setInput(reader);

            int eventType = xpp.getEventType();

            while (eventType != XmlPullParser.END_DOCUMENT) {
                String tagName = xpp.getName();

                switch (eventType) {
                    case XmlPullParser.START_TAG:
                        if (tagName.equalsIgnoreCase("track")) {
                            currentXmlAlbumTrack = new XmlTracks();
                        }
                        break;

                    case XmlPullParser.TEXT:
                        curText = xpp.getText();
                        break;

                    case XmlPullParser.END_TAG:
                        if (tagName.equals("track")) {
                            xmlTrackItems.add(currentXmlAlbumTrack);
                        } else if (tagName.equals("name")) {
                            currentXmlAlbumTrack.setTrackName(curText);
                            Log.d("tag","name: " + curText);
                        } else if (tagName.equalsIgnoreCase("url")) {
                            //TODO
                        } else if (tagName.equalsIgnoreCase("duration")){
                            //TODO
                        }
                        break;

                    default:
                        break;

                }
                eventType = xpp.next();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

I only want to parse the name tags that are inside of each track tag.

So basically I want to parse all the track names (8 of them) into a ListView, but when I use currentXmlAlbumTrack.setTrackName(curText); it tries to output every name tag inside the XML file, like this:

D/tag: name text: Now, Diabolical
D/tag: name text: Now, Diabolical
D/tag: name text: Satyricon
D/tag: name text: K.I.N.G.
D/tag: name text: Satyricon
D/tag: name text: The Pentagram Burns
D/tag: name text: Satyricon
D/tag: name text: A New Enemy
D/tag: name text: Satyricon
D/tag: name text: The Rite of Our Cross
D/tag: name text: Satyricon
D/tag: name text: That Darkness Shall Be Eternal
D/tag: name text: Satyricon
D/tag: name text: Delirium
D/tag: name text: Satyricon
D/tag: name text: To the Mountains
D/tag: name text: Satyricon
D/tag: name text: black metal
D/tag: name text: albums I own
D/tag: name text: Black n Roll
D/tag: name text: Norwegian Black Metal
D/tag: name text: metal

Is there any way to avoid this without completely rewriting the parser?

2 Answers 2

0

You could try with getDepth() https://developer.android.com/reference/org/xmlpull/v1/XmlPullParser.html#getDepth()

It returns the depth of an element, so for the name you are interested in, the depth should be 4, since the root depth is 1. It takes just a minor change to your code in the last case statment, checking the depth with xpp.getDepth()==4:

                    case XmlPullParser.END_TAG:
                    if (tagName.equals("track")) {
                        xmlTrackItems.add(currentXmlAlbumTrack);
                    } else if (tagName.equals("name") && xpp.getDepth()==4) {
                        currentXmlAlbumTrack.setTrackName(curText);
                        Log.d("tag","name: " + curText);
                    } else if (tagName.equalsIgnoreCase("url")) {
                        //TODO
                    } else if (tagName.equalsIgnoreCase("duration")){
                        //TODO
                    }
                    break;
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for replying, but sadly this does nothing, since values inside tags/tag/name are also at depth 4.
Sorry, my bad. I overseen the name tag inside tags/tag. Please check if the alternative solution does the job.
0

Alternative solution would be to add a flag that is raised when a track tag is found, cleared at the end of track tag and checked at the name tag:

try {
    XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
    XmlPullParser xpp = factory.newPullParser();

    FileInputStream fis = ctx.openFileInput("AlbumInfo.xml");

    BufferedReader reader = new BufferedReader(new InputStreamReader(fis));

    xpp.setInput(reader);

    int eventType = xpp.getEventType();

    // add flag to distinguish parent tag
    bool isTrack=false;

    while (eventType != XmlPullParser.END_DOCUMENT) {
        String tagName = xpp.getName();

        switch (eventType) {
            case XmlPullParser.START_TAG:

                // WRONG PLACE, IT SHOULD BE INSIDE IF !!!
                // isTrack=true; // <track> tag found

                if (tagName.equalsIgnoreCase("track")) {
                    currentXmlAlbumTrack = new XmlTracks();

                    isTrack=true; // <track> tag found

                }
                break;

            case XmlPullParser.TEXT:
                curText = xpp.getText();
                break;

            case XmlPullParser.END_TAG:
                if (tagName.equals("track")) {

                    isTrack=false; // </track> end tag found

                    xmlTrackItems.add(currentXmlAlbumTrack);
                } else if (tagName.equals("name") && isTrack) {
                    currentXmlAlbumTrack.setTrackName(curText);
                    Log.d("tag","name: " + curText);
                } else if (tagName.equalsIgnoreCase("url")) {
                    //TODO
                } else if (tagName.equalsIgnoreCase("duration")){
                    //TODO
                }
                break;

            default:
                break;

        }
        eventType = xpp.next();
    }
} catch (Exception e) {
    e.printStackTrace();
}

2 Comments

I tried this and it still logged all the 22 <name> tag values to the console. When I try to parse it through to a ListView I get Attempt to invoke virtual method 'void XmlTracks.setTrackName(java.lang.String)' on a null object reference. I have given up on finding an elegant solution, so I basically added all 22 values to a string array and used for (int i = 0; i<size*2;i=i+2) where size is the number of <track> tags found in the xml, and looped through the values only parsing every second entry. It's not the best solution, but works since I use this parser for tracks only.
Sorry, again I've maid a mistake. Look at the code, it should work now!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.