Android org.xmlpull.В1.XmlPullParserException при анализе XML
у меня есть ситуация, когда я вызываю веб-службу, и она возвращает мне HTML в XML-конверте. например:
<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>
Я должен получить ссылка на prev-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;
}
}
Он бросает XmlPullParserException об исполнении парсер.nextText() ... и значение элемента text в это время равно .. я думаю, что он неправильно понимает это значение с тегом start из-за наличия в тексте..
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.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)
надеюсь, я прояснил свою проблему.
решение
Isnpired by Мартин подход преобразования полученного сначала данные в строку, я управлял своей проблемой в своего рода смешанном подходе.
-
преобразовать полученный InputStream ' s значение строки и заменил ошибочные символы на * (или что вы хотите): следующим образом
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()));
надеюсь, это кому-то поможет!
1 ответов
Да, исключение, вероятно, вызвано, потому что это недопустимый XML в соответствии с разделом 2.4 символьные данные и разметка в спецификации XML 1.0:
[...] левая угловая скобка (
Если вы поместите этот XML в Eclipse, Eclipse будет жаловаться на недопустимость XML. Если вы можете исправить веб-службу, вы должны исправить созданный XML либо с помощью ссылок на сущности, таких как <
и с помощью CDATA.
Если у вас нет власти над веб-службой, я думаю, что проще всего будет разобрать это вручную с помощью некоторого пользовательского кода, возможно, используя регулярные выражения в зависимости от того, насколько смягчены требования обобщенности у вас.
Пример Кода
вот как вы могли бы проанализировать 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