解析 XML 时出现 Android org.xmlpull.v1.XmlPullParserException

标签 android android-xml xmlpullparser

我有这样一种情况,我调用了一个网络服务,它在 XML 信封中返回了一些 HTML。喜欢:

<xml version="1.0" cache="false">
<head/>
<body>
<table>
<tr>
   <td>
        <a href="link-to-prev-post">
           <text color="red"><< Prev</text>
        </a>
   </td>
   <td>
        <a href="link-to-next-post">
           <text color="red">| Next >></text>
        </a>
   </td>
</tr>
</table>
</body>
</xml>

我必须检索 link-to-prev-postlink-to-next-post 链接.. 这样我就可以通过这些链接获取更多数据。

我正在使用 XmlPullParser 来解析上面提供的 XML/HTML。要获取下一个/上一个项目的链接,我正在执行以下操作:

if (xmlNodeName.equalsIgnoreCase("a")) {
                link = parser.getAttributeValue(null, "href");

            } else if (xmlNodeName.equalsIgnoreCase("text")) {
                color = parser.getAttributeValue(null, "color");

                if (color.equalsIgnoreCase("red") && parser.getEventType() == XmlPullParser.START_TAG) {
                        // check for next/prev blog entries links
                        // but this parser.nextText() throws XmlPullParserException
                        // i think because the nextText() returns << Prev which the parser considers to be wrong
                        String innerText = parser.nextText();
                        if (innerText.contains("<< Prev")) {
                            blog.setPrevBlogItemsUrl(link);                             
                        } else if (innerText.contains("Next >>")) {
                            blog.setNextBlogItemsUrl(link);
                        }
                    }

                    link = null;
                }
            }

在执行parser.nextText()时抛出XmlPullParserException ...此时文本元素的值为<< Prev .. 我认为由于文本中存在 << ,所以它误解了带有开始标记的值..

LogCat 详细信息是:

04-08 18:32:09.827: W/System.err(688): org.xmlpull.v1.XmlPullParserException: precondition: START_TAG (position:END_TAG </text>@9:2535 in java.io.InputStreamReader@44c6d0d8) 
04-08 18:32:09.827: W/System.err(688):  at org.kxml2.io.KXmlParser.exception(KXmlParser.java:245)
04-08 18:32:09.827: W/System.err(688):  at org.kxml2.io.KXmlParser.nextText(KXmlParser.java:1382)
04-08 18:32:09.827: W/System.err(688):  at utilities.XMLParserHelper.parseBlogEntries(XMLParserHelper.java:139)
04-08 18:32:09.827: W/System.err(688):  at serviceclients.PlayerSummaryAsyncTask.doInBackground(PlayerSummaryAsyncTask.java:68)
04-08 18:32:09.827: W/System.err(688):  at serviceclients.PlayerSummaryAsyncTask.doInBackground(PlayerSummaryAsyncTask.java:1)
04-08 18:32:09.836: W/System.err(688):  at android.os.AsyncTask$2.call(AsyncTask.java:185)
04-08 18:32:09.836: W/System.err(688):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
04-08 18:32:09.836: W/System.err(688):  at java.util.concurrent.FutureTask.run(FutureTask.java:137)
04-08 18:32:09.836: W/System.err(688):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
04-08 18:32:09.836: W/System.err(688):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
04-08 18:32:09.836: W/System.err(688):  at java.lang.Thread.run(Thread.java:1096)

我希望我已经澄清了我的问题。

解决方案

灵感来自 Martin's首先将接收到的数据转换为字符串的方法,我用一种混合方法解决了我的问题。

  1. 将接收到的InputStream的值转换为字符串,并将错误的字符替换为*(或任何你想要的):如下

    InputStreamReader isr = new InputStreamReader(serviceReturnedStream);
    
    BufferedReader br = new BufferedReader(isr);
    StringBuilder xmlAsString = new StringBuilder(512);
    String line;
    try {
        while ((line = br.readLine()) != null) {
            xmlAsString.append(line.replace("<<", "*").replace(">>", "*"));
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    
  2. 现在我有一个包含正确 XML 数据的字符串(对于我的情况),所以只需使用普通的 XmlPullParser 来解析它而不是自己手动解析它:

    XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
    
    factory.setNamespaceAware(false);
    
    XmlPullParser parser = factory.newPullParser();
    parser.setInput(new StringReader(xmlAsString.toString()));
    

希望这对某人有帮助!

最佳答案

是的,可能会抛出异常,因为根据 2.4 Character Data and Markup 节,这是无效的 XML在 XML 1.0 规范中:

[...] the left angle bracket (<) MUST NOT appear in [its] literal form, [...]

如果您将该 XML 放入 Eclipse,Eclipse 将提示 XML 无效。如果您能够修复 Web 服务,则应该修复生成的 XML,方法是使用 < 等实体引用或使用 CDATA。 .

如果您无法控制 Web 服务,我认为最简单的方法是使用一些自定义代码手动解析它,也许使用 regular expressions ,取决于您对通用性的要求有多宽松。

示例代码

下面是解析上述 XML 文件的方法。请注意,您可能希望改进此代码以使其更通用,但您至少应该从以下内容着手:

    // Read the XML into a StringBuilder so we can get get a Matcher for the
    // whole XML
    InputStream xmlResponseInputStream = // Get InputStream to XML somehow
    InputStreamReader isr = new InputStreamReader(xmlResponseInputStream);
    BufferedReader br = new BufferedReader(isr);
    StringBuilder xmlAsString = new StringBuilder(512);
    String line;
    try {
        while ((line = br.readLine()) != null) {
            xmlAsString.append(line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    // Look for links using a regex. Assume the first link is "Prev" and the
    // next link is "Next"
    Pattern hrefRegex = Pattern.compile("<a href=\"([^\"]*)\">");
    Matcher m = hrefRegex.matcher(xmlAsString);
    String linkToPrevPost = null;
    String linkToNextPost = null;
    while (m.find()) {
        String hrefValue = m.group(1);
        if (linkToPrevPost == null) {
            linkToPrevPost = hrefValue;
        } else {
            linkToNextPost = hrefValue;
        }
    }

    Log.i("Example", "'Prev' link = " + linkToPrevPost + 
            " 'Next' link = " + linkToNextPost);

对于您的 XML 文件,logcat 的输出将是

I/Example (12399): 'Prev' link = link-to-prev-post 'Next' link = link-to-next-post

关于解析 XML 时出现 Android org.xmlpull.v1.XmlPullParserException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10063397/

相关文章:

android - 如何在 Android 中创建一个 AttributeSet?

java - XmlStreamReader 未读取完整的文本值

android - 方向改变时处理 SQLiteOpenHelper

Android JNI - 如何正确释放在 C native 函数中分配的内存

android - 如何在布局中均匀对齐 ImageButtons

android - android中带有背景颜色的圆角按钮

c# - 使用 Xamarin 实现新的 Google 登录

android - 如何在android mapview中为特定区域着色?

android - 以编程方式在 GridLayout 中设置 layout_column 和 layout_row

java - Android:XmlPullParserFactory.newInstance 说找不到符号类 newInstance