项目中要添加RSS源,显示RSS的所有文章,刚好测试的是新浪的新闻RSS源,各种百度之后,找到了这位前辈写的用SAXParser模式解析xml文件的代码,只要参考这个链接,绝对每个小白都可以轻松的解析基本上的RSS源,链接如下:SAXParser解析正常的RSS源例子,大概的流程就是根据xml的节点,先建立一个类,用来保存各个节点数据,然后写一个类继承DefaultHandler,重写那四个方法,将数据存入到list中,最后就是关键的一个功能代码,根据给出的URL正式解析,功能代码如下:
URL url = new URL(urlStr);
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); // 构建SAX解析工厂
SAXParser saxParser = saxParserFactory.newSAXParser(); // 解析工厂生产解析器
XMLReader xmlReader = saxParser.getXMLReader(); // 通过saxParser构建xmlReader阅读器
RssHandler rssHandler = new RssHandler();
xmlReader.setContentHandler(rssHandler);
// 使用url打开流,并将流作为 xmlReader解析的输入源并解析
InputSource inputSource = new InputSource(url.openStream());
xmlReader.parse(inputSource);
return rssHandler.getRssFeed();
上面的解析基本上的RSS源都没有问题,比如这个链接:public final String RSS_URL ="http://zaobao.feedsportal.com/c/34003/f/616930/index.rss";是可以正常解析的,问题来了,如果你恰好使用的是新浪财经要闻RSS源,那恭喜你,你中奖了,使用上述前辈的代码,你只能拿得到日期或者具体link,其他关于title以及具体的详细信息,都拿不到值,贴出新浪财经要闻的xml文件如下:
<span style="font-size: 12px;"><?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" title="XSL Formatting" href="/show_new_final.xsl" media="all"?>
<rss version="2.0">
<channel>
</span><span style="font-size:24px;color:#cc0000;"><em><title>
<![CDATA[财经要闻汇总-新浪财经]]>
</title>
<image>
<title>
<![CDATA[财经要闻汇总-新浪财经]]>
</title>
<link>http://finance.sina.com.cn/</link>
<url>http://i1.sinaimg.cn/cj/pic/newLogo/logo_home_fin.gif</url>
</image>
<description>
<![CDATA[财经要闻汇总]]>
</description>
<link>http://news.sina.com.cn/news1000/index.shtml?requestOrder=7</link>
<language>zh-cn</language>
<generator>WWW.SINA.COM.CN</generator>
<ttl>5</ttl>
<copyright>
<![CDATA[Copyright 1996 - 2015 SINA Inc. All Rights Reserved]]>
</copyright>
<pubDate>Fri, 11 Sep 2015 09:35:08 GMT</pubDate>
<category>
<![CDATA[]]>
</category></em></span><span style="font-size: 12px;">
</span><span style="font-size:24px;color:#cc0000;"><strong><item></strong></span><span style="font-size: 12px;">
<title>
<![CDATA[FBS外汇:亚洲股市低迷 避险助推欧元上涨]]>
</title>
<link>http://go.rss.sina.com.cn/redirect.php?url=http://finance.sina.com.cn/money/forex/20150911/173423224617.shtml</link>
<author>WWW.SINA.COM.CN</author>
<guid>http://go.rss.sina.com.cn/redirect.php?url=http://finance.sina.com.cn/money/forex/20150911/173423224617.shtml</guid>
<category>
<![CDATA[财经要闻汇总]]>
</category>
<pubDate>Fri, 11 Sep 2015 09:34:41 GMT</pubDate>
<comments></comments>
<description>
<![CDATA[ 周五亚洲股市开盘涨跌不一,因美联储下周重要利率会议前夕,市场风险因素增加,投资者因此显得较为谨慎。周四除了美国股市外,全球大部分股市收跌,更加剧了投资者紧张情绪,市场对下周不会加息的预期升温,美元资产遭到抛售。美联储仍有较大可能会在下周召开的利率会议上宣布....]]>
</description>
</span><strong><span style="font-size:24px;color:#cc0000;"></item></span></strong><span style="font-size: 12px;">
<item>
<title>
<![CDATA[英国央行称民众加息预期升至四年新高]]>
</title>
<link>http://go.rss.sina.com.cn/redirect.php?url=http://finance.sina.com.cn/world/20150911/173223224593.shtml</link>
<author>WWW.SINA.COM.CN</author>
<guid>http://go.rss.sina.com.cn/redirect.php?url=http://finance.sina.com.cn/world/20150911/173223224593.shtml</guid>
<category>
<![CDATA[财经要闻汇总]]>
</category>
<pubDate>Fri, 11 Sep 2015 09:32:51 GMT</pubDate>
<comments></comments>
<description>
<![CDATA[ 新浪美股讯 北京时间11日下午消息 彭博报道称英国央行周五表示,认为未来12个月利率将会上调的英国民众比例升至2011年以来的最高水平。
英国央行8月通胀态度调查显示,50%的受访者认为目前处于0.5%记录低位的关键利率将会在明年8月底前上调,5月调查时持有这一观点的受....]]>
</description>
</item>
<item>
<title>
<![CDATA[苗圩:做好智能制造十三五规划编制工作]]>
</title>
<link>http://go.rss.sina.com.cn/redirect.php?url=http://finance.sina.com.cn/china/20150911/173123224590.shtml</link>
<author>WWW.SINA.COM.CN</author>
<guid>http://go.rss.sina.com.cn/redirect.php?url=http://finance.sina.com.cn/china/20150911/173123224590.shtml</guid>
<category>
<![CDATA[财经要闻汇总]]>
</category>
<pubDate>Fri, 11 Sep 2015 09:31:34 GMT</pubDate>
<comments></comments>
<description>
<![CDATA[ 中国证券网讯 9月11日从工信部获悉,9月10日,工业和信息化部组织召开智能制造试点示范经验交流电视电话会议,工业和信息化部部长苗圩出席会议并作重要讲话,部装备工业司司长张相木主持会议。
苗圩指出,要用好试点示范这个重要抓手。推进智能制造是一项复杂而庞大的....]]>
</description>
</item>
</channel>
</rss></span>
原因如下: 这个新浪RSS源和其他的xml文件不同的是在channel节点下面,跟的不是item节点,是出乎意料的title节点,所以上述代码无法识别,解决方案是判断首个节点是否为item,有则新建一个保存数据的类,没有则不创建,关键代码如下:
package client.verbank.mtp.allone.frame.ForeignNewsFragment.RSSUtil;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class RssHandler extends DefaultHandler {
RssFeed rssFeed = null;
RssItem rssItem = null;
String lastElementName = "";// 标记变量,用于标记在解析过程中我们关心的几个标签,若不是我们关心的标签记做0
final int RSS_TITLE = 1;// 若是 title 标签,记做1,注意有两个title,但我们都保存在item的成员变量中
final int RSS_LINK = 2;// 若是 link 标签,记做2
final int RSS_DESCRIPTION = 3;// 若是 description 标签,记做3
final int RSS_CATEGORY = 4;// 若是category标签,记做 4
final int RSS_PUBDATE = 5; // 若是pubdate标签,记做5,注意有两个pubdate,但我们都保存在item的pubdate成员变量中
int currentFlag = 0;
private StringBuilder sb = new StringBuilder();
@Override
public void startDocument() throws SAXException {
super.startDocument();
rssFeed = new RssFeed();
// rssItem = new RssItem();
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
super.characters(ch, start, length);
sb.append(ch, start, length);
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
sb.setLength(0);
<span style="font-size:24px;color:#cc0000;">if ("item".equals(localName)) {
rssItem = new RssItem();
}</span>
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
super.endElement(uri, localName, qName);
String value = sb.toString();
// System.out.println(value + "value的值为");
// System.out.println(localName + "localName的值为");
<span style="font-size:24px;color:#cc0000;"><strong> if (rssItem == null) {
return;
}</strong></span>
if ("title".equals(localName)) {
rssItem.setTitle(value.trim());
} else if ("description".equals(localName)) {
rssItem.setDescription(value);
} else if ("link".equals(localName)) {
rssItem.setLink(value);
} else if ("pubDate".equals(localName)) {
rssItem.setPubdate(value);
} else if ("category".equals(localName)) {
rssItem.setCategory(value);
}
// 如果解析一个item节点结束,就将rssItem添加到rssFeed中。
if ("item".equals(localName)) {
rssFeed.addItem(rssItem);
}
}
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
public RssFeed getRssFeed() {
return rssFeed;
}
}
这样就顺利的解决了xml文件中,开头不是正常的item节点,以及有些节点包含:<![CDATA[财经要闻汇总-新浪财经]]>的问题,成功解决!!!感谢同事的指导,一开始还没仔细看过新浪的RSSxml文件,以为代码有错误,后来才发现是没有对空指针的情况进行判断,希望有遇到同样问题的人有一点帮助。
=====================分割线2016年3月11日09:04:29,当需要解析总节点上的title和每个item的所有信息,使用以上解析的方法无法完成解析,而且需要同时解析多个rss源方法更新如下=====
代码如下:
public List<RssFeed> getFeeds(String url) {
List<RssFeed> feedList = new ArrayList<RssFeed>();
String[] rssUrlVec = url.split(",");
for (String rss : rssUrlVec) {
RssFeed rssFeed = new RssFeed();
try {
URL rssUrl = new URL(rss);
XMLNode xmlNode = XMLCaptain.parseStream(rssUrl.openStream());
for (int i = 0; i < xmlNode.getSubNodeSize(); i++) {
XMLNode node = xmlNode.getSubNode(i);
if (node.getName().equalsIgnoreCase("channel")) {
for (int j = 0; j < node.getSubNodeSize(); j++) {
XMLNode channelNode = node.getSubNode(j);
if (channelNode.getName().equalsIgnoreCase("title")) {
rssFeed.setTitle(channelNode.getValue());
}
if (channelNode.getName().equalsIgnoreCase("item")) {
RssItem item = new RssItem();
for (int k = 0; k < channelNode
.getSubNodeSize(); k++) {
XMLNode itemNode = channelNode
.getSubNode(k);
if (itemNode.getName().equalsIgnoreCase(
"title")) {
item.setTitle(itemNode.getValue());
} else if (itemNode.getName()
.equalsIgnoreCase("link")) {
item.setLink(itemNode.getValue());
} else if (itemNode.getName()
.equalsIgnoreCase("pubdate")) {
item.setPubdate(itemNode.getValue());
} else if (itemNode.getName()
.equalsIgnoreCase("description")) {
item.setDescription(itemNode.getValue());
} else if (itemNode.getName()
.equalsIgnoreCase("category")) {
item.setCategory(itemNode.getValue());
}
}
rssFeed.addItem(item);
}
}
}
}
} catch (Exception e) {
continue;
}
feedList.add(rssFeed);
}
return feedList;
}