안드로이드에서 XML 파싱에 XmlPullParser를 사용하는 것이 효과적이고 유지보수 가능한 방법입니다. 역사적으로 안드로이드엔 이 인터페이스의 두가지 구현이 있습니다.
KXmlParser, XmlPullParserFactory.newPullParser()를 통합니다.
ExpatPullParser, Xml.newPullParser()를 통합니다.
Xml.newPullPaser()의 구현은 nextText()를 호출 시 문서에 명시한 END_TAG로의 진입을 항상하지 못하는 버그가 있습니다. 그래서 몇몇 앱에서 추가적인 next()나 nextTag()를 호출해서 이를 회피하고 있습니다.
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>"));
}
아이스크림 샌드위치에서 우리는 KXmlParser를 리턴하도록 Xml.newPullParser()를 변경했고 ExpatPullParser 클래스를 삭제했습니다. 이 변경은 nextTag() 버그를 고치죠. 불행히도 현재 버그를 회피하던 앱들이 아이스크림 샌드위치에서 망가질 수 있습니다.
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)
이 수정된 코드는 현재 위치가 END_TAG가 아닐 경우에만 nextText ()호출 후 nextTag()를 호출합니다.
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);
}
위의 코드는 모든 릴리즈에서 XML을 정확히 파싱합니다. 만약 당신의 앱에서 nextText()가 널리 쓰이고 있다면 nextText()를 호출 곳에 이 헬퍼 메서드를 이용하세요.
private String safeNextText(XmlPullParser parser)
throws XmlPullParserException, IOException {
String result = parser.nextText();
if (parser.getEventType() != XmlPullParser.END_TAG) {
parser.nextTag();
}
return result;
}
단일한 XmlPullParser로 간 점이 유지보수를 단순하게 만들고 우리가 더 많은 에너지를 성능 향상에 쓸 수 있게 합니다.
댓글 없음:
댓글 쓰기