Home  >  Article  >  Backend Development  >  Be careful with the XmlPullParser.netText() method

Be careful with the XmlPullParser.netText() method

黄舟
黄舟Original
2017-02-09 13:58:141729browse

Using XmlPullParser on Android is a highly efficient and easy-to-maintain method of parsing XML. Android has historically had two implementation classes that implement this interface:

  • KXmlParser, via XmlPullParserFactory.newPullParser().

  • ExpatPullParser, via Xml.newPullParser().

There is a bug in the implementation of Xml.newPullParser() calling nextText(), nextText() is not always executed prior to END_TAG as mentioned in the documentation.

Therefore, some applications may have bugs in additional calls to next() or nextTag();

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=&#39;1.0&#39;?>"  
            + "<menu>"  
            + "  <item>Waffles</item>"  
            + "  <item>Coffee</item>"  
            + "</menu>"));  
}

In android 4.0, Xml.newPullParser() has been changed to return the KxmlParser class, and at the same time Removed ExpatPullParser class. This fixes the nextTag() bug.

Unfortunately, the current applications that may crash are all versions lower than android 4.0. The following is the error message.

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)

The solution is to jump to nextTag() only after calling nextText(), only when the current position is not END_TAG.

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);  
 }

The above code can correctly parse all xml versions. If the application uses nextText() extensively, use the following auxiliary method where nextText() is used.

private String safeNextText(XmlPullParser parser)  
         throws XmlPullParserException, IOException {  
     String result = parser.nextText();  
     if (parser.getEventType() != XmlPullParser.END_TAG) {  
         parser.nextTag();  
     }  
     return result;  
 }

Using a single XmlPullParse simplifies our maintenance and allows us to spend more energy on improving system performance.

The above is the content of the Be careful with the XmlPullParser.netText() method. For more related content, please pay attention to the PHP Chinese website (www.php.cn)!


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Previous article:android XPath parsing xmlNext article:android XPath parsing xml