【问题标题】:XmlPullParser handling multidimensional repeated elementsXmlPullParser 处理多维重复元素
【发布时间】:2015-09-02 14:19:24
【问题描述】:

我试图从我的 XML 中获取顶级元素的列表(包含重复的子元素)

示例 XML

<feed>
   <folder name="subfolder1">
       <file name="subfile1" />
       <file name="subfile2" />
       <folder name="subsubfolder1">
            <file name="subsubfile1" />
            <file name="subsubfile2" />
        </folder>
   </folder>
   <folder name="subfolder2">
       <file name="subfile1" />
       <file name="subfile2" />
       <folder name="subsubfolder1">
            <file name="subsubfile1" />
            <file name="subsubfile2" />
        </folder>
   </folder>
   <file name="file1"/>
</feed>

我正在尝试获取顶级元素的所有名称的列表,例如

.subfolder1
.subfolder2

这是我的 FeedReader....

private List<Entry> readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {
        List<Entry> entries = new ArrayList<Entry>();

        Log.v("ab", "reed feed started");

        parser.require(XmlPullParser.START_TAG, ns, "feed");
        while (parser.next() != XmlPullParser.END_TAG) {

            if (parser.getEventType() != XmlPullParser.START_TAG) {
                continue;
            }
            String sectionName = parser.getName();

            if(sectionName.equals("folder")) {
                readFolder(parser);
            } 
        }

        return entries;
    }

private void readFolder (XmlPullParser parser) throws XmlPullParserException, IOException  {
        parser.require(XmlPullParser.START_TAG, ns, "folder");
        Log.v("ab", parser.getAttributeValue(null, "name"));
        parser.require(XmlPullParser.END_TAG, ns, "folder");
    }

这是我的 LogCat....

09-02 13:40:22.537  31736-31753/? V/ab reed feed started
09-02 13:40:22.537  31736-31753/? V/ab﹕ subfolder1

任何人都可以帮助解决为什么在找到文件夹元素的第一个实例后停止?

【问题讨论】:

    标签: android xml android-xmlpullparser


    【解决方案1】:

    您的最后一个 parser.require 行似乎有问题:

    parser.require(XmlPullParser.END_TAG, ns, "folder");
    

    From the documentation, 你在这里所做的是检查是否满足这些条件,如果不满足,则抛出异常。因此,您当前位于刚刚阅读的“文件夹”开始标记处,并且正在检查您是否位于“文件夹”结束标记处。由于您不在“文件夹”结束标记处,因此 parser.require 将引发异常。

    如果您删除该行,它应该让您的 while 循环继续运行,直到下一个文件夹开始标记。

    编辑:这是一个完整的解决方案

    我们需要一直持续到文档末尾,而不仅仅是任何 END_TAG,所以我将您的 while 循环修改为 while (parser.next() != XmlPullParser.END_DOCUMENT),然后在 readFolder 方法调用之后添加了一些额外的代码。如果我理解正确,您只会在名为“子文件夹”的文件夹之后并跳过“子子文件夹”。所以我包含了一个应该跳过这些的循环。 我还删除了 parser.require 行,因为我个人没有看到需要,但这只是一种方法。

    private List<Entry> readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {
        List<Entry> entries = new ArrayList<Entry>();
    
        Log.v("ab", "reed feed started");
    
        while (parser.next() != XmlPullParser.END_DOCUMENT) {
    
            if (parser.getEventType() != XmlPullParser.START_TAG) {
                continue;
            }
            String sectionName = parser.getName();
    
            if(sectionName.equals("folder")) {
                readFolder(parser);
    
                //these booleans will be used to help us skip the subfolders
                boolean finishedTopLevelElement = false;
                boolean unwantedSubFolderFound = false;
    
                //this will loop until we are at a "folder" tag and have 
                //confirmed we have finished with the top level folder
                while (!(("folder".equals(parser.getName())) && finishedTopLevelElement)){
                    parser.next();
    
                    //we only care about 'folder' tags, for anything else
                    //we keep looping
                    if ("folder".equals(parser.getName())){
    
                        if (parser.getEventType() == XmlPullParser.START_TAG){
    
                            //if we hit a folder start tag, we're at a sub-folder
                            unwantedSubFolderFound = true;
    
                        } else if (parser.getEventType() == XmlPullParser.END_TAG && !unwantedSubFolderFound){
    
                            //if we hit a 'folder' end tag and we've not got an unwanted subfolder then
                            //we're done, it's the end tag of the top-level folder
                            finishedTopLevelElement = true;
                            unwantedSubFolderFound = false;
    
                        } else {
    
                            //if it's a folder end tag and we HAVE previously found an unwanted sub folder start tag
                            //then we've successfully skipped that sub-folder and can keep looking
                            unwantedSubFolderFound = false;
                        }
                    }
    
    
                }
            } 
        }
    
        return entries;
    }
    
    private void readFolder (XmlPullParser parser) throws XmlPullParserException, IOException  {
        Log.v("ab", parser.getAttributeValue(null, "name"));
    }
    

    【讨论】:

    • 嗨刘易斯,我已经尝试删除该行,但它仍然只给出第一个文件夹名称:/任何其他想法?
    • @AndrewBramwell 我已经编辑了上面的答案,希望它很清楚。我已经在代码中添加了 cmets,但如果您有任何问题,请告诉我。
    • 哦,我的日子!非常感谢你花时间为我做这件事!当我即将旅行时,我现在无法测试,但我应该能够在今晚晚些时候进行测试,我会在稍后报告/接受答案以及什么。再次感谢您!
    • 没问题,我最近不得不自己做一些 XML 解析,所以巩固和分享知识很有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多