问题描述
我在 android 中使用 xmlpullparser 来解析一个如下所示的 xml 文档:
<top> <category> <name></name> <desc></desc> <songs> <song> <clip></clip> <thumb></thumb> </song> <song> <clip></clip> <thumb></thumb> </song> </songs> </category> </top>
我试过这个:
while (eventType != XmlPullParser.END_DOCUMENT && !done){ String name = null; switch (eventType){ case XmlPullParser.START_DOCUMENT: categoriesSong = new ArrayList<TopMousika>(); break; case XmlPullParser.START_TAG: name = parser.getName(); if (name.equalsIgnoreCase(CATEGORY)){ currentCategory = new TopMousika(); currentCategory.setId(parser.getAttributeValue(0)); currentCategory.setId(parser.getAttributeValue(1)); } else if (currentCategory != null){ if (name.equalsIgnoreCase(NAME)){ currentCategory.setName(parser.nextText()); } else if (name.equalsIgnoreCase(DESCRIPTION)){ currentCategory.setDescription(parser.nextText()); } else if (name.equalsIgnoreCase(THUMBNAIL)){ currentCategory.setThumbnail(parser.nextText()); } else if (name.equalsIgnoreCase(SONGS)){ songs = new ArrayList<SongMousika>(); if(name.equalsIgnoreCase(SONG)){ currentSong = new SongMousika(); currentSong.setId(parser.getAttributeValue(0)); Log.d("TEST", "OK"); songs.add(currentSong); } else if (name.equalsIgnoreCase(TITLE)){ Log.d("TEST", "OK2"); currentSong.setTitle(parser.nextText()); } else if (name.equalsIgnoreCase(SINGER)){ currentSong.setTitle(parser.nextText()); } else if (name.equalsIgnoreCase(THUMBNAIL)){ currentSong.setTitle(parser.nextText()); } else if (name.equalsIgnoreCase(PUBLICATION_DATE)){ currentSong.setTitle(parser.nextText()); } else if (name.equalsIgnoreCase(CLIP)){ currentSong.setTitle(parser.nextText()); } currentCategory.setSongs(songs); } } break; case XmlPullParser.END_TAG: name = parser.getName(); if (name.equalsIgnoreCase(CATEGORY) && currentCategory != null){ currentCategory.setSongs(songs); categoriesSong.add(currentCategory); } else if (name.equalsIgnoreCase(TOP)){ done = true; } break; } eventType = parser.next(); }
但我无法检索我的歌曲列表.
有人可以帮我吗?
推荐答案
你似乎期待 name 在检查之间神奇地改变:
if (name.equalsIgnoreCase(SONGS)) { songs = new ArrayList<SongMousika>(); if(name.equalsIgnoreCase(SONG)) {
SONG 和 SONGS会怎样?您需要不断提取 XML 并对循环中的每个元素名称做出不同的反应.因此,在对 START_TAG 事件作出反应时,您可能会有一堆没有任何嵌套的 if/else if 语句.(顺便说一下,很可能值得将其处理到一个单独的方法中.)
编辑:好的,所以你需要让循环的每次迭代只对一个标签做出反应.因此,您对开始标记的处理类似于:
case XmlPullParser.START_TAG: name = parser.getName(); if (name.equalsIgnoreCase(CATEGORY)){ currentCategory = new TopMousika(); currentCategory.setId(parser.getAttributeValue(0)); currentCategory.setId(parser.getAttributeValue(1)); } else if (currentCategory != null) { if (name.equalsIgnoreCase(NAME)){ currentCategory.setName(parser.nextText()); } else if (name.equalsIgnoreCase(DESCRIPTION)){ currentCategory.setDescription(parser.nextText()); } else if (name.equalsIgnoreCase(THUMBNAIL)){ currentCategory.setThumbnail(parser.nextText()); } else if (name.equalsIgnoreCase(SONGS)){ songs = new ArrayList<SongMousika>(); } else if (songs != null) { if(name.equalsIgnoreCase(SONG)) { currentSong = new SongMousika(); currentSong.setId(parser.getAttributeValue(0)); Log.d("TEST", "OK"); songs.add(currentSong); } else if (currentSong != null) { else if (name.equalsIgnoreCase(TITLE)) { Log.d("TEST", "OK2"); currentSong.setTitle(parser.nextText()); } else if (name.equalsIgnoreCase(SINGER)){ currentSong.setSinger(parser.nextText()); } else if (name.equalsIgnoreCase(THUMBNAIL)) // etc } } }
请注意,在通过那里的任何路径中,我们从不检查 name 是否具有多个值 - 我们说:
- 我们是否要开设一个新类别?
- 如果是,请创建并记住它 - 然后继续下一次迭代.
- 如果没有(如果我们有一个类别),我们是否要开始一个新的歌曲列表?
- 如果是,请创建并记住它 - 然后继续下一次迭代.
- 如果没有(如果我们有歌曲列表),我们是否要开始一首新歌?
- 如果是,请创建并记住它 - 然后继续下一次迭代.
- 如果没有(如果我们有一首歌)...
- 我们在读标题吗?如果是这样,请阅读文本并进行设置,然后继续.
- 我们在读歌手吗?如果是这样,请阅读文本并进行设置,然后继续.
- 我们正在阅读缩略图吗?如果是这样,请阅读文本并进行设置,然后继续.
- 等
问题描述
i'm using xmlpullparser in android to parse an xml document that looks like :
<top> <category> <name></name> <desc></desc> <songs> <song> <clip></clip> <thumb></thumb> </song> <song> <clip></clip> <thumb></thumb> </song> </songs> </category> </top>
I tried this :
while (eventType != XmlPullParser.END_DOCUMENT && !done){ String name = null; switch (eventType){ case XmlPullParser.START_DOCUMENT: categoriesSong = new ArrayList<TopMousika>(); break; case XmlPullParser.START_TAG: name = parser.getName(); if (name.equalsIgnoreCase(CATEGORY)){ currentCategory = new TopMousika(); currentCategory.setId(parser.getAttributeValue(0)); currentCategory.setId(parser.getAttributeValue(1)); } else if (currentCategory != null){ if (name.equalsIgnoreCase(NAME)){ currentCategory.setName(parser.nextText()); } else if (name.equalsIgnoreCase(DESCRIPTION)){ currentCategory.setDescription(parser.nextText()); } else if (name.equalsIgnoreCase(THUMBNAIL)){ currentCategory.setThumbnail(parser.nextText()); } else if (name.equalsIgnoreCase(SONGS)){ songs = new ArrayList<SongMousika>(); if(name.equalsIgnoreCase(SONG)){ currentSong = new SongMousika(); currentSong.setId(parser.getAttributeValue(0)); Log.d("TEST", "OK"); songs.add(currentSong); } else if (name.equalsIgnoreCase(TITLE)){ Log.d("TEST", "OK2"); currentSong.setTitle(parser.nextText()); } else if (name.equalsIgnoreCase(SINGER)){ currentSong.setTitle(parser.nextText()); } else if (name.equalsIgnoreCase(THUMBNAIL)){ currentSong.setTitle(parser.nextText()); } else if (name.equalsIgnoreCase(PUBLICATION_DATE)){ currentSong.setTitle(parser.nextText()); } else if (name.equalsIgnoreCase(CLIP)){ currentSong.setTitle(parser.nextText()); } currentCategory.setSongs(songs); } } break; case XmlPullParser.END_TAG: name = parser.getName(); if (name.equalsIgnoreCase(CATEGORY) && currentCategory != null){ currentCategory.setSongs(songs); categoriesSong.add(currentCategory); } else if (name.equalsIgnoreCase(TOP)){ done = true; } break; } eventType = parser.next(); }
but I can not retrieve my Songs List.
can any one help me please ?
推荐答案
You seem to be expecting name to change magically between checks:
if (name.equalsIgnoreCase(SONGS)) { songs = new ArrayList<SongMousika>(); if(name.equalsIgnoreCase(SONG)) {
How is it going to be SONG and SONGS? You need to keep pulling XML and react to each element name differently in the loop. So you'll probably have a bunch of if/else if statements without any nesting when reacting to a START_TAG event. (It's very likely to be worth pulling the handling of that into a separate method, by the way.)
EDIT: Okay, so you need to make each iteration of the loop just react to one tag. So your handling for a start tag would be something like:
case XmlPullParser.START_TAG: name = parser.getName(); if (name.equalsIgnoreCase(CATEGORY)){ currentCategory = new TopMousika(); currentCategory.setId(parser.getAttributeValue(0)); currentCategory.setId(parser.getAttributeValue(1)); } else if (currentCategory != null) { if (name.equalsIgnoreCase(NAME)){ currentCategory.setName(parser.nextText()); } else if (name.equalsIgnoreCase(DESCRIPTION)){ currentCategory.setDescription(parser.nextText()); } else if (name.equalsIgnoreCase(THUMBNAIL)){ currentCategory.setThumbnail(parser.nextText()); } else if (name.equalsIgnoreCase(SONGS)){ songs = new ArrayList<SongMousika>(); } else if (songs != null) { if(name.equalsIgnoreCase(SONG)) { currentSong = new SongMousika(); currentSong.setId(parser.getAttributeValue(0)); Log.d("TEST", "OK"); songs.add(currentSong); } else if (currentSong != null) { else if (name.equalsIgnoreCase(TITLE)) { Log.d("TEST", "OK2"); currentSong.setTitle(parser.nextText()); } else if (name.equalsIgnoreCase(SINGER)){ currentSong.setSinger(parser.nextText()); } else if (name.equalsIgnoreCase(THUMBNAIL)) // etc } } }
Note how in any path through there we never check for name having multiple values - we say:
- Are we starting a new category?
- If so, create it and remember it - then continue with the next iteration.
- If not (and if we've got a category), are we starting a new song list?
- If so, create it and remember it - then continue with the next iteration.
- If not (and if we've got a song list), are we starting a new song?
- If so, create it and remember it - then continue with the next iteration.
- If not (and if we've got a song)...
- Are we reading the title? If so, read the text and set it, then continue.
- Are we reading the singer? If so, read the text and set it, then continue.
- Are we reading the thumbnail? If so, read the text and set it, then continue.
- etc