2011-09-16 59 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