请注意Android中的 XmlPullParser.nextText()
使用XmlPullParser 在Android上来解析XML文件是高效可维护的。由于历史原因,Android系统上有两种实现:
- KXmlParser, 通过 XmlPullParserFactory.newPullParser() 函数获取
- ExpatPullParser, 通过 Xml.newPullParser() 函数获取
而
Xml.newPullParser()的实现有个bug,当调用函数
nextText() 后并不一定像文档描述的那样总是前进到END_TAG。一些程序可能使用再次调用next() 或者 nextTag()函数来解决这个问题。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public
void
parseXml(Reader reader)
throws
XmlPullParserException, IOException {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(reader);
parser.nextTag();
parser.require(XmlPullParser.START_TAG,
null
,
"menu"
);
while
(parser.nextTag() == XmlPullParser.START_TAG) {
parser.require(XmlPullParser.START_TAG,
null
,
"item"
);
String itemText = parser.nextText();
parser.nextTag();
// this call shouldn’t be necessary!
parser.require(XmlPullParser.END_TAG,
null
,
"item"
);
System.out.println(
"menu option: "
+ itemText);
}
parser.require(XmlPullParser.END_TAG,
null
,
"menu"
);
}
public
static
void
main(String[] args)
throws
Exception {
new
Menu().parseXml(
new
StringReader(
"<?xml version='1.0'?>"
+
"<menu>"
+
" <item>Waffles</item>"
+
" <item>Coffee</item>"
+
"</menu>"
));
}
|
在冰激凌三明治(Android 4.0)版本中,Android团队修改了Xml.newPullParser()函数的实现,返回KxmlParser 并且删除了ExpatPullParser 类。这样修复了nextTag() bug。不幸的是那些按照上面的代码修改该bug的程序在4.0系统上运行将会崩溃。
1
2
3
4
|
org.xmlpull.v1.XmlPullParserException: expected: END_TAG {
null
}item (position:START_TAG <item>
@1
:
37
in java.io.StringReader
@40442fa8
)
at org.kxml2.io.KXmlParser.require(KXmlParser.java:
2046
)
at com.publicobject.waffles.Menu.parseXml(Menu.java:
25
)
at com.publicobject.waffles.Menu.main(Menu.java:
32
)
|
可以按照如下的方式来修复该问题,调用函数nextText()后只有当前位置不是END_TAG 的时候才调用nextTag()。
1
2
3
4
5
6
7
8
9
|
while
(parser.nextTag() == XmlPullParser.START_TAG) {
parser.require(XmlPullParser.START_TAG,
null
,
"item"
);
String itemText = parser.nextText();
if
(parser.getEventType() != XmlPullParser.END_TAG) {
parser.nextTag();
}
parser.require(XmlPullParser.END_TAG,
null
,
"item"
);
System.out.println(
"menu option: "
+ itemText);
}
|
上面的代码在所有的Android版本上都能正常运行。如果您的程序使用了nextText()函数,请使用下面的助手函数来替代所有的nextText()函数调用:
1
2
3
4
5
6
7
8
|
private
String safeNextText(XmlPullParser parser)
throws
XmlPullParserException, IOException {
String result = parser.nextText();
if
(parser.getEventType() != XmlPullParser.END_TAG) {
parser.nextTag();
}
return
result;
}
|
现在只使用一个 XmlPullParser 实现,可以让维护系统更简单并且可以让Android开发团队集中精力在提高系统性能上面。
原文转载自 云在千峰: http://yunfeng.sinaapp.com/?p=278#ixzz1uRWXn2Qi