2011-09-16 126 views
1

我正在用RSS閱讀器製作一個非常簡單的應用程序。讀者的作品很棒,但它只是給了我標題,我也想要說明。 我對android非常陌生,而且我嘗試了很多東西,但是我無法讓它工作。 我發現了很多解析器,但它們讓我很難理解,所以我希望找到一個簡單的解決方案,因爲它只是我想要的標題和描述。 任何人都可以幫助我嗎?Java -Android。解析器問題

import java.io.IOException; 
import java.net.MalformedURLException; 
import java.net.URL; 

import javax.xml.parsers.ParserConfigurationException; 
import javax.xml.parsers.SAXParser; 
import javax.xml.parsers.SAXParserFactory; 

import org.xml.sax.Attributes; 
import org.xml.sax.InputSource; 
import org.xml.sax.SAXException; 
import org.xml.sax.XMLReader; 
import org.xml.sax.helpers.DefaultHandler; 

import android.app.Activity; 
import android.os.Bundle; 
import android.widget.TextView; 

public class NyhedActivity extends Activity { 
    String streamTitle = ""; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     // TODO Auto-generated method stub 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.nyheder); 

     TextView result = (TextView)findViewById(R.id.result); 

      try { 
     URL rssUrl = new URL("http://tv2sport.dk/rss/*/*/*/248/*/*"); 
     SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance(); 
     SAXParser mySAXParser = mySAXParserFactory.newSAXParser(); 
     XMLReader myXMLReader = mySAXParser.getXMLReader(); 
     RSSHandler myRSSHandler = new RSSHandler(); 
     myXMLReader.setContentHandler(myRSSHandler); 
     InputSource myInputSource = new InputSource(rssUrl.openStream()); 
     myXMLReader.parse(myInputSource); 

     result.setText(streamTitle); 

     } catch (MalformedURLException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
     result.setText("Cannot connect RSS!"); 
     } catch (ParserConfigurationException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
     result.setText("Cannot connect RSS!"); 
     } catch (SAXException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
     result.setText("Cannot connect RSS!"); 
     } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
     result.setText("Cannot connect RSS!"); 
     } 


     } 

     private class RSSHandler extends DefaultHandler 
     { 
     final int stateUnknown = 0; 
     final int stateTitle = 1; 
     int state = stateUnknown; 

     int numberOfTitle = 0; 
     String strTitle = ""; 
     String strElement = ""; 

     @Override 
     public void startDocument() throws SAXException { 
     // TODO Auto-generated method stub 
     strTitle = "Nyheder fra "; 
     } 

     @Override 
     public void endDocument() throws SAXException { 
     // TODO Auto-generated method stub 
     strTitle += ""; 
     streamTitle = "" + strTitle; 
     } 

     @Override 
     public void startElement(String uri, String localName, String qName, 
     Attributes attributes) throws SAXException { 
     // TODO Auto-generated method stub 
     if (localName.equalsIgnoreCase("title")) 
     { 
     state = stateTitle; 
     strElement = ""; 
     numberOfTitle++; 
     } 
     else 
     { 
     state = stateUnknown; 
     } 
     } 

     @Override 
     public void endElement(String uri, String localName, String qName) 
     throws SAXException { 
     // TODO Auto-generated method stub 
     if (localName.equalsIgnoreCase("title")) 
     { 
     strTitle += strElement + "\n"+"\n"; 
     } 
     state = stateUnknown; 
     } 

     @Override 
     public void characters(char[] ch, int start, int length) 
     throws SAXException { 
     // TODO Auto-generated method stub 
     String strCharacters = new String(ch, start, length); 
     if (state == stateTitle) 
     { 
     strElement += strCharacters; 
     } 
     } 
    } 

} 
+0

您發佈的代碼甚至不會*嘗試*閱讀說明,它只包含標題的代碼。 –

+0

我知道這是因爲我刪除了其他代碼,因爲它把所有東西搞砸了。 我正在尋找一個解決方案,使其正確:) – Kano

回答

1

我從來沒有真正使用過SAX,當談到在Java中解析XML時。我總是使用JDOM。它很簡單,而且非常易於使用。

要讀取一個XML文件,JDOM,您創建一個文檔,並使用一個InputStream和SAXBuilder的填充:

SAXBuilder builder = new SAXBuilder(); 
Document document = builder.builder(myInputStream); 

在您發佈情況:myInputStream = url.openStream();

然後,你需要獲取XML文檔的根:

Element root = document.getRootElement(); 

現在它非常簡單。因爲我不知道你會得到的XML的結構,我就認爲它看起來像:

<rssfeed> 
    <news> 
    <title> Title </title> 
    <description> Description </description> 
    </news> 
    <news> 
    <title> ... </title> 
    <description> ... </description> 
    </news> 
    <news> 
    <title> ... </title> 
    <description> ... </description> 
    </news> 
<rssfeed> 

然後,您可以列出這樣的所有元素:

List<Element> news = root.getChildren("news"); 

然後你在列表中的for-each循環中運行,得到了標題和描述(有一個數據類來保存這些信息是如新聞類的信息):

ArrayList<News> newsList = new ArrayList<News>(); 
for(Element child : news) { 
    News news = new News(); 
    news.setTitle(child.getChildText("title"); 
    news.setDescription(child.getChildText("description"); 
    newsList.add(news); 
} 

現在你有一個你c的新聞列表一場戲。

+0

感謝您的建議,但答案是目前我的技能水平略高。我發現了很多教程,但目前我不明白每一行代碼,這使我很難編寫自己的解析器類。 我得到的數據是: 標題 描述 Kano

+0

使用JDOM的想法,是解析類已爲你寫的,所有你需要的是用它來獲取你需要的數據。一旦您下載JDOM並將其添加到您的項目構建路徑中,您應該可以實際上覆制粘貼我的示例。你所需要做的就是用「item」替換字符串「news」,它應該可以工作。 – kaspermoerch

+0

謝謝。我會嘗試,即使我不確定我能做到這一點:) – Kano

0

我希望我可以幫助你:

@Override 
    public void endElement(String uri, String localName, String qName) 
    throws SAXException { 
    // TODO Auto-generated method stub 
    if (localName.equalsIgnoreCase("title")) 
    { 
    strTitle += strElement + "\n"+"\n"; 
    } 
    else if (localName.equalsIgnoreCase("lead")) 
    { 
    lead += strElement + "\n"+"\n"; 
    } 
    } 
+0

我試過了,但它不會工作。爲什麼領先?這不是描述嗎? 您可以將其寫入我上面發佈的代碼中,只是爲了確保我所做的一切正確嗎? – Kano

1

卡諾,

可以簡化你的生活,並通過利用SJXP寫這個RSS提要解析器得到top-notch performance(免責聲明:我是作者) 。

SJXP是一個very-very thin abstraction layer,它位於XML Pull Parsing API之上(Android提供了它自己的功能,因此您只有sjxp.JAR依賴項,XPP3適用於其他平臺),並允許您使用類似XPath的分析規則將簡單的規則與文檔的某些位置進行匹配,然後告訴解析從這些位置需要的信息。

我爲你寫了一個Eclipse項目的示例,它解析了6分鐘內TV2體育爲你提供的信息(我將在底部鏈接它)。

主要方法是這樣的,所以你得到流程的想法:

public static void main(String[] args) throws IllegalArgumentException, 
    XMLParserException, IOException { 
// Location we want to parse. 
URL feedURL = new URL("http://tv2sport.dk/rss/*/*/*/248/*/*"); 

// List we will hold all parsed stories in. 
List<Item> itemList = new ArrayList<Item>(); 

// Get all the rules we will use to parse this file 
IRule[] rules = createRules(); 

// Create the parser and populate it with the rules. 
XMLParser<List<Item>> parser = new XMLParser<List<Item>>(rules); 

// Parse the RSS feed. 
parser.parse(feedURL.openStream(), itemList); 

// Print the results. 
System.out.println("Parsed " + itemList.size() + " RSS items."); 

for (Item i : itemList) 
    System.out.println("\t" + i); 
} 

你看流動與創造我們的列表來保存我們的項目中,我們從文檔解析它們開始。然後我們得到一組IRule實例給解析器,然後創建解析器並給它在工作時使用的規則。

然後,我們調用對feed內容的parse方法,並將它傳遞給所謂的「用戶對象」,更具體地說,只是我們希望它傳遞給規則的任何事件的實例執行。

在這種情況下,我們希望訪問我們的List,因此我們可以添加項目,所以我們只需將它傳入,解析器在執行時將它傳遞給我們的IRule logic,以便我們可以使用它。

Item類使用只是一個簡單的POJO來保存數據,並打印好看:

public class Item { 
    public String title; 
    public String description; 

    @Override 
    public String toString() { 
     return "Item [title='" + title + "', description='" + description + "']"; 
    } 
} 

所有有趣的事情發生在你的iRule,可以定義你的目標是什麼樣的元素(人物數據,屬性數據或僅標記打開/關閉事件),然後從IRule接口重寫適當的方法以提供執行某些操作的處理程序。

例如,這裏是一個分析的標題的處理程序:

IRule<List<Item>> itemDescRule = new DefaultRule<List<Item>>(Type.CHARACTER, "/rss/channel/item/description") { 
    @Override 
    public void handleParsedCharacters(XMLParser<List<Item>> parser, String text, List<Item> userObject) { 
     Item item = userObject.get(userObject.size() - 1); 
     item.description = text; 
    } 
}; 

你看,你得到給定的解析器實例本身(這樣你就可以觸發「停止」的方法,如果你想提前結束解析),你得到的是文字是字符數據,你得到的是'用戶對象'恰好是我們的列表傳遞給你的。

我們抓住我們正在填充的項目,給它的描述,就是這樣。 2行代碼。

還有另外一個IRule,每次遇到開放標籤時都會向列表中添加一個新項目,這就是我們後續的規則就像這樣只是從列表中彈出結尾元素並填充它。

當你運行該項目,輸出看起來是這樣的:

Parsed 50 RSS items. 
    Item [title='Barcas bøddel beæret over Barca-føler', description='Tirsdag snød Thiago Silva Barcelona for tre point, da han headede AC Milans udligning i kassen i Champions League-kampens overtid.'] 
    Item [title='Guardiola: Pato hurtigere end Usain Bolt', description='FC Barcelona-træner, Josep Guardiola, er dybt imponeret af Milan-målscoreren Alexandre Patos hurtighed.'] 
    Item [title='Milan-profil: Vi kan nå semifinalen', description='Clarence Seedorf mener, at AC Milan kan nå semifinalerne i Champions League efter 2-2 i Barcelona.'] 
    <SNIP...> 

您可以下載我爲你here創建的整個Eclipse項目。

希望有所幫助。

+0

非常感謝您的所有工作。明天我會看看它。 我找到了解決方案,但我會看看你的項目,看看你的解決方案是否更好:)我會在稍後發表評論。 – Kano