【问题标题】:Android Studio Java XmlPullParser how to get only certain tag valuesAndroid Studio Java XmlPullParser 如何仅获取某些标记值
【发布时间】:2023-03-07 18:38:01
【问题描述】:

我在解析一些 xml 标记时遇到问题。我对 Android 开发非常陌生,但我仍在努力学习基础知识。

如果这篇文章有点难以阅读,我很抱歉。

我想阅读我下载的以下 XML 文件:

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

我用我的 XmlPullParser 类阅读它:

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

我只想解析每个track 标签内的name 标签。

所以基本上我想将所有曲目名称(其中 8 个)解析为 ListView,但是当我使用 currentXmlAlbumTrack.setTrackName(curText); 时,它会尝试输出 XML 文件中的每个名称标签,如下所示:

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

有什么办法可以在不完全重写解析器的情况下避免这种情况?

【问题讨论】:

    标签: java android xml xmlpullparser android-xmlpullparser


    【解决方案1】:

    你可以试试 getDepth() https://developer.android.com/reference/org/xmlpull/v1/XmlPullParser.html#getDepth()

    它返回元素的深度,因此对于您感兴趣的名称,深度应该是 4,因为根深度是 1。在最后一个 案例 语句,使用 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;
    

    【讨论】:

    • 感谢您的回复,但遗憾的是这没有任何作用,因为标签/标签/名称中的值也在深度 4。
    • 对不起,我的错。我监督标签/标签内的名称标签。请检查替代解决方案是否有效。
    【解决方案2】:

    另一种解决方案是添加一个标志,该标志在找到 track 标记时引发,在 track 标记的末尾清除并在 name 处检查 标签:

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

    【讨论】:

    • 我试过了,它仍然将所有 22 个 标记值记录到控制台。当我尝试将其解析为 ListView 时,我得到 尝试在空对象引用上调用虚拟方法“void XmlTracks.setTrackName(java.lang.String)”。我已经放弃寻找一个优雅的解决方案,所以我基本上将所有 22 个值添加到一个字符串数组并使用 for (int i = 0; i&lt;size*2;i=i+2) 其中 size 是在 xml 中找到的 标记的数量,并循环遍历仅每秒解析一次的值入口。这不是最好的解决方案,但因为我只将此解析器用于轨道,所以它可以工作。
    • 对不起,我又弄错了。看看代码,现在应该可以了!
    猜你喜欢
    • 2020-12-30
    • 1970-01-01
    • 2020-11-01
    • 2014-03-22
    • 2021-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多