问题
I'm trying to get the name and reading type="alpha".
I'm a beginner and English is not my first language, please pardon me. I've read about DOM, SAX, Simple, other StackOverflow posts, other samples but I don't understand and will like to learn about XMLPullParser in this case.
Sample XML below:
<feed>
<title>Title</title>
<item>
<entry>
<name>Name1</name>
<record date="20001231">
<reading type="alpha" value="100"/>
<reading type="beta" value="200"/>
</record>
</entry>
<entry>
<name>Name2</name>
<record date="20001231">
<reading type="alpha" value="300"/>
<reading type="beta" value="400"/>
</record>
</entry>
</item>
</feed>
I've read this: http://developer.android.com/training/basics/network-ops/xml.html and the sample code works for the sample XML above without the <item> tags to get the name and record date.
private List<Entry> readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {
List<Entry> entries = new ArrayList<Entry>();
parser.require(XmlPullParser.START_TAG, ns, "feed");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
if (parser.getName().equals("entry")) {
entries.add(readEntry(parser));
} else {
skip(parser);
}
}
return entries;
}
What I've tried with the presence of <item> tags (but does not work) is:
private List<Entry> readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {
List<Entry> entries = new ArrayList<Entry>();
parser.require(XmlPullParser.START_TAG, ns, "feed");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
if (parser.getName().equals("item")) {
parser.next();
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
if (parser.getName().equals("entry")) {
entries.add(readEntry(parser));
} else {
skip(parser);
}
}
} else {
skip(parser);
}
}
return entries;
}
If I can solve that, I will be able to read the name and record date, but what I'm trying to get is the name and reading type="alpha", which I don't know how to get the nested reading type="alpha".
Many thanks in advance.
回答1:
you keep looping and when
parser.getEventType() == XmlPullParser.START_TAG && parser.getName().equals("name")
you can retrive the value of the tag name with getText()
:
you will call then
parser.next();
String name = parser.getText();
when
parser.getEventType() == XmlPullParser.START_TAG && parser.getName().equals("reading")
you want to read your attributes, Eg. <reading type="alpha" value="300"/>
String type = parser.getAttributeValue(null, "type");
String value = parser.getAttributeValue(null, "value");
Edit:
private void readFeed(XmlPullParser parser) throws IOException, XmlPullParserException {
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
String name = parser.getName();
if (name == null) {
continue;
}
if (name.equals("reading")) {
Log.e(getClass().getSimpleName()," " + parser.getAttributeValue(null, "type"));
Log.e(getClass().getSimpleName(), " " + parser.getAttributeValue(null, "value"));
}
}
eventType = parser.next();
}
}
回答2:
You can try this function
private List readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {
List entries = new ArrayList();
parser.require(XmlPullParser.START_TAG, ns, "feed");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
// Starts by looking for the item tag
if (name.equals("item")) {
parser.require(XmlPullParser.START_TAG, ns, "item");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
// and then get the entry here
if (name.equals("entry")) {
entries.add(readEntry(parser));
}
}
} else {
skip(parser);
}
}
return entries;
}
Where readEntry Function is :
private Entry readEntry(XmlPullParser parser) throws XmlPullParserException, IOException {
parser.require(XmlPullParser.START_TAG, ns, "entry");
String name = null;
Record record = null;
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
if (name.equals("name")) {
parser.require(XmlPullParser.START_TAG, ns, "name");
String title = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, "name");
} else if (name.equals("record")) {
// Try to figure it out by yourself for practice ;)
} else {
skip(parser);
}
}
return new Entry(title, summary, link);
}
回答3:
I also got same error and my solution was simple just check right
String name=parser.getName();
parser.require(XmlPullParser.START_TAG, nameSpace, first_tag_key);
if name and first_tag_right is not same then you will get this exception.
THIS IS A GENERIC ANSWER FOR ANY USER IF IN CASE HE GET THIS ERROR.
回答4:
The accepted answer works only because you only have nested tags but what if you had unnested tags and you only wanted the nested ones ?
One way you can do this is :
while (eventType != XmlPullParser.END_DOCUMENT ) {
// check for the parent tag
if (eventType == XmlPullParser.START_TAG && "item".equals(xpp.getName())) {
eventType = xpp.next();
// loop the parent tag elements until we reach the end of the parent tag
while (eventType != XmlPullParser.END_TAG && !"item".equals(xpp.getName())) {
// check the children tags
if ("title".equals(xpp.getName()))
// do something
else if ("link".equals(xpp.getName()))
// do something
xpp.next();
}
}
eventType = xpp.next();
}
The basic idea is one while loop for each parent tag and corresponding ifs for each children.
来源:https://stackoverflow.com/questions/33341391/difficulty-with-xml-nested-tags-with-xmlpullparser-in-android