Android 解析新浪RSS新闻源 问题汇总和解决

      项目中要添加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文件如下:




	
		
			<![CDATA[财经要闻汇总-新浪财经]]>
		
		
			
				<![CDATA[财经要闻汇总-新浪财经]]>
			
			http://finance.sina.com.cn/
			http://i1.sinaimg.cn/cj/pic/newLogo/logo_home_fin.gif
		
		
			
		
		http://news.sina.com.cn/news1000/index.shtml?requestOrder=7
		zh-cn
		WWW.SINA.COM.CN
		5
		
			
		
		Fri, 11 Sep 2015 09:35:08 GMT
		
			
		
		
			
				<![CDATA[FBS外汇:亚洲股市低迷 避险助推欧元上涨]]>
			
			http://go.rss.sina.com.cn/redirect.php?url=http://finance.sina.com.cn/money/forex/20150911/173423224617.shtml
			WWW.SINA.COM.CN
			http://go.rss.sina.com.cn/redirect.php?url=http://finance.sina.com.cn/money/forex/20150911/173423224617.shtml
			
				
			
			Fri, 11 Sep 2015 09:34:41 GMT
			
			
				
			
		
		
			
				<![CDATA[英国央行称民众加息预期升至四年新高]]>
			
			http://go.rss.sina.com.cn/redirect.php?url=http://finance.sina.com.cn/world/20150911/173223224593.shtml
			WWW.SINA.COM.CN
			http://go.rss.sina.com.cn/redirect.php?url=http://finance.sina.com.cn/world/20150911/173223224593.shtml
			
				
			
			Fri, 11 Sep 2015 09:32:51 GMT
			
			
				
			
		
		
			
				<![CDATA[苗圩:做好智能制造十三五规划编制工作]]>
			
			http://go.rss.sina.com.cn/redirect.php?url=http://finance.sina.com.cn/china/20150911/173123224590.shtml
			WWW.SINA.COM.CN
			http://go.rss.sina.com.cn/redirect.php?url=http://finance.sina.com.cn/china/20150911/173123224590.shtml
			
				
			
			Fri, 11 Sep 2015 09:31:34 GMT
			
			
				
			
		

	

    原因如下:  这个新浪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);
		if ("item".equals(localName)) {

			rssItem = new RssItem();
		}

	}

	@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的值为");
		if (rssItem == null) {
			return;
		}
		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节点,以及有些节点包含:的问题,成功解决!!!感谢同事的指导,一开始还没仔细看过新浪的RSSxml文件,以为代码有错误,后来才发现是没有对空指针的情况进行判断,希望有遇到同样问题的人有一点帮助。


=====================分割线2016年3月11日09:04:29,当需要解析总节点上的title和每个item的所有信息,使用以上解析的方法无法完成解析,而且需要同时解析多个rss源方法更新如下=====


代码如下:

public List getFeeds(String url) {
		List feedList = new ArrayList();
		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;
	}


你可能感兴趣的:(Android)