我有一种情况,我称之为Web服务,它会在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-post &amp; 链接到下一个帖子链接..所以我可以通过这些链接获得更多数据。
我正在使用 XmlPullParser 来解析上面提供的XML / HTML。要获取next / prev项目的链接,我的工作如下:
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 ...此时文本元素的值为&lt;&lt;上一页 ..我认为由于文本中存在&lt;&lt; ,因此误解了此值与启动标记。
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方法将接收到的数据首先转换为字符串,我用一种混合方法管理我的问题。
将收到的 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();
}
现在我有一个包含正确XML数据的字符串(对于我的情况),所以只需使用普通的XmlPullParser来解析它而不是自己手动解析它:
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(false);
XmlPullParser parser = factory.newPullParser();
parser.setInput(new StringReader(xmlAsString.toString()));
希望这有助于某人!
答案 0 :(得分:6)
是的,可能会引发异常,因为根据XML 1.0规范中的2.4 Character Data and Markup部分,这是无效的XML:
[...]左尖括号(&lt;)不得以[其]字面形式出现,[...]
如果将该XML放在Eclipse中,Eclipse会抱怨XML无效。如果您能够修复Web服务,则应通过使用<
等实体引用或使用CDATA来修复生成的XML。
如果您对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