Parse RSS feed for Android

2019-01-26 20:38发布

问题:

This is an example RSS feed.

http://na.leagueoflegends.com/en/rss.xml

<channel>
  <title>Most Recent News</title>
  <link>http://na.leagueoflegends.com/en/rss.xml</link>
  <description/>
  <language>en-US</language>
  <item>
    <title>Community-recommended bundles available now </title>
    <link>http://na.leagueoflegends.com/en/news/store/sales/community-recommended-bundles-available-now?ref=rss</link>
    <description>&lt;div class="field field-name-field-body-small field-type-text-long field-label-hidden">Craving something new at champ select? Get fed on these limited-time bundles based on players’ suggestions!&lt;/div>&lt;div class="field field-name-field-article-media field-type-file field-label-hidden">&lt;div id="file-11675" class="file file-image file-image-jpeg">  &lt;img typeof="foaf:Image" src="/sites/default/files/styles/large/public/upload/bundle-banner_1.jpg?itok=4MD_leb5" width="480" height="270" alt="" title="" />&lt;/div>&lt;/div>&lt;div class="field field-name-custom-author field-type-entityreference field-label-hidden">&lt;span class="article_detail">&lt;span class="posted_by">By WizardCrab&lt;/span>&lt;/span>&lt;/div></description>
    <pubDate>Mon, 30 Jun 2014 19:35:11 +0000</pubDate>
    <dc:creator>sbroome</dc:creator>
    <guid isPermaLink="false">18268 at http://na.leagueoflegends.com</guid>
  </item>
  <item>
    <title>Champion and skin sale: 07.04 - 07.07</title>
    <link>http://na.leagueoflegends.com/en/news/store/sales/champion-and-skin-sale-0704-0707?ref=rss</link>
    <description>&lt;div class="field field-name-field-body-small field-type-text-long field-label-hidden">Grab these champions and skins on sale for 50% off for a limited time:&lt;/div>&lt;div class="field field-name-field-article-media field-type-file field-label-hidden">&lt;div id="file-13873" class="file file-image file-image-jpeg">  &lt;img typeof="foaf:Image" src="/sites/default/files/styles/large/public/upload/mu842qnf.jpg?itok=OktrEQdQ" width="480" height="270" alt="" title="" />&lt;/div>&lt;/div>&lt;div class="field field-name-custom-author field-type-entityreference field-label-hidden">&lt;span class="article_detail">&lt;span class="posted_by">By WizardCrab&lt;/span>&lt;/span>&lt;/div></description>
    <pubDate>Tue, 24 Jun 2014 21:24:10 +0000</pubDate>
    <dc:creator>sbroome</dc:creator>
    <guid isPermaLink="false">18060 at http://na.leagueoflegends.com</guid>
  </item>
  <item>
   ....
   ....
   .... (and goes on for a while)

I wanted to get eat attribute within the .

I am currently using

            URL rssFeedUrl = new URL(rssUrl);
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser saxParser = factory.newSAXParser();
            XMLReader xmlReader = saxParser.getXMLReader();
            RSSHandler rssHandler = new RSSHandler();
            xmlReader.setContentHandler(rssHandler);
            InputSource inputSource = new InputSource(rssFeedUrl.openStream());
            xmlReader.parse(inputSource);


private class RSSHandler extends DefaultHandler {

public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException {
                if (localName.equals("item")) {
                    item = true;
                }
                if(item) {
                    if(localName.equals(RSS_TITLE)) {

                    } else if(localName.equals(RSS_LINK)) {

                    } else if(localName.equals(RSS_DESCRIPTION)) { 

                    } else if(localName.equals(RSS_PUB_DATE)) {

                    } else if(localName.equals(RSS_CREATOR)) {

                    } else if(localName.equals(RSS_GUID)) {

                    }

                }
                if (!localName.equals("item") && item == true) {
                    rssResult = rssResult + "\n\n" + localName + ": ";
                }


            }

            public void endElement(String namespaceURI, String localName, String qName) throws SAXException {

            }

            public void characters(char[] ch, int start, int length) throws SAXException {
                String cdata = new String(ch, start, length);
                if (item == true) {
                    String x = (cdata.trim()).replaceAll("\\s+", " ");
                    rssResult = rssResult + x + "\t";
                }
            }

Is there a simpler way? Cause right now it is too tedious. I basically want to say getElement("description")

回答1:

Just as CommonsWare mentioned, you should probably use a third party RSS library for this if you want to keep it simple. The newest RSS library in the Android Arsenal is one I made: PkRSS https://github.com/Pkmmte/PkRSS

The API is extremely simple yet flexible.

// Loads your RSS feed in a background thread
PkRSS.with(this).load(url).async();

// After it has finished loading, use this to get the result
List<Article> articleList = PkRSS.with(this).get(url);

Of course, there are a lot more details if you visit the GitHub page for this library.



回答2:

I'd use a third-party RSS-parsing library. Four are presently listed in the RSS category on the Android Arsenal.

If not, if the RSS file is likely to be large, I would use SAX and not complain. If you are sure that the RSS file will be small, the DOM parser will give you an API that is more in line with what you are seeking, but it tends to be slower and more memory-intensive.



回答3:

I found the whole SAX thing difficult to look at. I wrote my own parser for RSS, Atom & RDF.

Try MvNewsFeed class in my AndroidWithoutStupid library on GitHub. https://github.com/vsubhash/AndroidWithoutStupid

MvGeneral.startSyncDownload("http://www.example.com/rss.xml", "/mnt/sdcard/rss.xml");
MvNewsFeed oFeed = new MvNewsFeed("/mnt/sdcard/rss.xml");
for (int i = 0; i < oFeed.moMessages.size(); i++) {
  Log.d("YOUR_TAG", oFeed.moMessages.get(i).msMessageTitle);
  Log.d("YOUR_TAG", oFeed.moMessages.get(i).msMessageContent);
  Log.d("YOUR_TAG", oFeed.moMessages.get(i).msMessageLink);
}

For brevity, I have used a synchronous download method. There is a separate class for asynchronous downloads - MvAsyncDownload. Call the constructor with same parameters.