2012-04-08 22 views
7

Web servisini aradığım bir durum var ve bir XML zarfında bana biraz HTML döndürüyor. gibi:XML ayrıştırılırken Android 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> 

ben bu bağlantıların sağladığı -linki önceki sonrası & -linki yeni yazı bağlantılar .. bu yüzden alabilirsiniz fazla veri almak zorundayız.

Yukarıdaki sağlanan XML/HTML'yi ayrıştırmak için XmlPullParser kullanıyorum. aşağıdaki gibi bir sonraki/önceki öğeleri için bağlantı elde etmek için, ben yapıyorum:

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

O parser.nextText() yürütülmesi üzerine XmlPullParserException ... ve bu metin öğesinin değerini atar zaman

LogCat detaydır .. ben çünkü metinde < <varlığının başlangıç ​​etiketiyle bu değeri misunderstands düşünüyorum .. Önceki< < geçerli:

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) 

Umarım problemimi açıklığa kavuştum.

Çözüm ilk dizeye alınan verileri dönüştürme Martin's yaklaşımla Isnpired

i karışık yaklaşımın bir tür sorunumu başardı.

  1. dizeye alınan inputStream 'ın değerini dönüştürme ve * ile hatalı karakterler değiştirilir (ya da her türlü istediğiniz): Şimdi ben doğru içeren bir dize var

    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. şöyle (benim durumumda için) XML veri, bu yüzden sadece elle kendim ayrıştırma yerine ayrıştırmak Normal XmlPullParser kullanın:

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

Umut, bu birilerine yardım eder!

cevap

6

Evet, istisna muhtemelen atılır XML 1.0 şartnamede bölüm 2.4 Character Data and Markup uyarınca geçersiz XML çünkü:

[...] sol açılı ayraç (<) [ortaya çıkmamalıdır onun ] bilgi formu, [...]

Bu XML'i Eclipse'e eklerseniz, Eclipse XML'in geçersiz olduğu konusunda şikayette bulunur. Web hizmetini düzeltebilirseniz, oluşturulan XML'yi &lt; gibi varlık referanslarını kullanarak veya CDATA kullanarak düzeltmelisiniz.

Web hizmetiniz üzerinde hiçbir gücünüz yoksa, elinizdeki genel rahatlık gereksinimlerine bağlı olarak, regular expressions kullanarak, bazı özel kodlarla el ile ayrıştırmanın en kolay yolu olacağını düşünüyorum.

Örnek Kod

Burada yukarıdaki XML dosyası ayrıştırmak gibi uygulayabilirsiniz. en azından muhtemelen daha genel hale getirmek için bu kodu geliştirmek istiyoruz unutmayın, ancak bir şey başlamak olmalıdır: XML dosyası ile

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

, LogCat çıkış olacak

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

Açıklama için teşekkürler ... aslında ben web hizmeti üzerinde herhangi bir kontrol sahibi değilim, bu yüzden ben neyin döndüğünü değiştiremiyorum ... normal ifadeler kullanarak iyi geliyor ama sorun, _parser.nextText() _ .. kullanarak veri okumaya çalıştığınızda ortaya çıkıyor Ben de regex bcoz olarak kullanılamaz düşünüyorum ben ilk regex ile ayrıştırmadan önce metin almak zorunda olacak .. ama eğer yapılabileceğini düşünüyorsanız o zaman lütfen bana biraz sağlayabilirsin bol örnek? bu harika olurdu. – Aamir

+0

Yardım etmekten mutluluk duyuyorum! Aslında tüm XML'i elle ayrıştırmaktan bahsediyordum, yani XML ayrıştırıcısını hiç kullanmıyordum (çünkü ayrıştırmakta olduğunuz XML değil). –

+0

Tamam şimdi umuyorum ... ama böyle el ile ayrıştırma yapmayı nasıl önerirsin? Ben bir örnek arıyorum ... Ben kötü bir şekilde sıkışmış var – Aamir

İlgili konular