2012-04-08 15 views
7

Tôi có một tình huống mà tôi gọi một dịch vụ web và nó trả về cho tôi một số HTML trong một phong bì XML. như:Android org.xmlpull.v1.XmlPullParserException khi phân tích cú pháp 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> 

tôi phải lấy dữ liệu link-to-prev-bài & link-to-next-bài liên kết .. vì vậy tôi có thể nhận được nhiều hơn thông qua những liên kết này.

Tôi đang sử dụng XmlPullParser để phân tích cú pháp XML/HTML được cung cấp ở trên. Để có được các liên kết cho các hạng mục/trước hôm sau, tôi đang làm như sau:

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

Nó ném XmlPullParserException về thi hành parser.nextText() ... và giá trị của các yếu tố văn bản tại đây thời gian là < < Trước .. tôi nghĩ rằng nó hiểu sai giá trị này với thẻ bắt đầu bởi vì sự hiện diện của < < trong văn bản ..

chi tiết LogCat là:

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) 

Tôi hy vọng tôi đã làm rõ vấn đề của mình.

Giải pháp

Isnpired bởi Martin's phương pháp chuyển đổi các dữ liệu nhận được đầu tiên chuỗi, tôi quản lý vấn đề của tôi trong một loại phương pháp hỗn hợp.

  1. Chuyển đổi giá trị nhận InputStream 's để chuỗi và thay thế các ký tự sai lầm với * (hoặc bất cứ điều gì bạn muốn): như sau

    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. Bây giờ tôi có một chuỗi chứa đúng Dữ liệu XML (cho trường hợp của tôi), do đó, chỉ cần sử dụng XmlPullParser bình thường để phân tích cú pháp thay vì phân tích cú pháp theo cách thủ công:

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

Hy vọng điều này sẽ giúp ai đó!

Trả lời

6

Vâng, ngoại trừ có lẽ ném bởi vì đó là XML hợp lệ theo phần 2.4 Character Data and Markup trong XML 1.0 đặc điểm kỹ thuật:

[...] khung góc trái (<) PHẢI KHÔNG xuất hiện trong [của nó ] dạng chữ, [...]

Nếu bạn đặt XML đó trong Eclipse, Eclipse sẽ phàn nàn về XML không hợp lệ. Nếu bạn có thể sửa chữa dịch vụ web, bạn nên sửa XML đã tạo bằng cách sử dụng các tham chiếu thực thể như &lt; hoặc bằng cách sử dụng CDATA.

Nếu bạn không có quyền truy cập dịch vụ web, tôi cho rằng cách dễ nhất là phân tích cú pháp thủ công với một số mã tùy chỉnh, có thể sử dụng regular expressions, tùy thuộc vào yêu cầu về tính phổ quát của bạn.

Mã ví dụ

Dưới đây là cách bạn có thể phân tích cú pháp tệp XML ở trên. Lưu ý rằng bạn có thể muốn cải thiện mã này để làm cho nó tổng quát hơn, nhưng bạn nên có một cái gì đó để bắt đầu với ít nhất:

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

Với tập tin XML của bạn, sản lượng để logcat sẽ

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

cảm ơn cho lời giải thích ... thực sự tôi không có quyền kiểm soát dịch vụ web nên tôi không thể thay đổi whats trả về ... bằng cách sử dụng biểu thức chính quy âm thanh tốt nhưng vấn đề phát sinh khi tôi cố gắng đọc dữ liệu bằng cách sử dụng _parser.nextText() _ .. vì vậy tôi nghĩ rằng regex không thể được sử dụng cũng như bcoz tôi sẽ phải đầu tiên nhận được văn bản trước khi phân tích nó thông qua regex .. nhưng nếu u nghĩ rằng nó có thể được thực hiện sau đó u có thể vui lòng cung cấp cho tôi một số s ví dụ phong phú ?? điều đó thật tuyệt. – Aamir

+0

Tôi rất vui được trợ giúp! Tôi đã thực sự đề cập đến việc phân tích cú pháp toàn bộ XML theo cách thủ công, tức là không sử dụng trình phân tích cú pháp XML chút nào (vì nó không phải là XML hợp lệ mà bạn đang phân tích cú pháp). –

+0

ok tôi umnderstand bây giờ .. nhưng làm thế nào u sẽ đề xuất phân tích thủ công như vậy? Tôi đang tìm kiếm một ví dụ .. tôi bị kẹt sai – Aamir