2012-04-08 523 views
7

我有一種情況,我調用了一個web服務,它返回一些XML信封中的HTML。像:解析XML時,org.xmlpull.v1.XmlPullParserException異常

<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> 

我必須找回通過這些鏈接鏈接到上一張,後 & 鏈接到下後鏈接..所以我可以得到更多的數據。

我正在使用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 ...和文本元素在這個值時間< <上一頁 ..我認爲這與誤解,因爲文本< <存在的開始標記這個值..

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 [email protected]) 
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方法Isnpired,我管理我的問題,是一種混合的方法。

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

希望這可以幫助別人!

回答

6

是,異常可能是拋出,因爲這是無效的XML作爲每部分2.4 Character Data and Markup在XML 1.0規範:

[...]的左尖括號(<)不能出現在[其]文字形式,[...]

如果您將該XML放入Eclipse中,Eclipse會抱怨XML無效。如果您能夠修復Web服務,則應該使用實體引用(例如&lt;)或使用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 
+0

感謝您的解釋...實際上我沒有控制的Web服務,所以我不能改變什麼返回...使用正則表達式聽起來不錯,但是當我嘗試使用_parser.nextText()__讀取數據時出現問題。 。所以我認爲正則表達式不能使用以及bcoz我將不得不先通過正則表達式解析它之前得到的文本..但如果你認爲它可以做到那麼可以請你給我一些充足的例子??那太好了。 – Aamir 2012-04-11 12:58:08

+0

我很高興幫助!我實際上是指手動解析整個XML,即根本不使用XML解析器(因爲它不是有效的XML解析)。 – 2012-04-12 06:34:25

+0

好吧,我現在明白了..但你會如何提出這種手動解析?我正在尋找一個例子..因爲我勉強卡住 – Aamir 2012-04-12 07:09:55

相關問題