`
该用户名已经存在
  • 浏览: 308556 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java获取网络RSS源并使用SAXParser解析

    博客分类:
  • Java
阅读更多
最近在项目中有一个需求就是读取网络RSS源数据,并将指定的节点生成json数据返回前端展示。要完成以上功能,首先了解三个知识点:
1. 什么是RSS源?
RSS源是一种描述和同步网站内容的格式,是目前使用最广泛的XML应用,一个RSS文件就是一段规范的XML数据,该文件一般以rss,xml或者rdf作为后缀。(摘自百度百科

2. 怎么读取网络资源?
最常见的读取网络资源的方式就是浏览器访问,浏览器封装一个网络请求到某个服务器上获取数据返回。也可以使用一些其他工具模拟网络请求获取数据返回。
在Java中,可以直接使用apache的HttpConnection请求网络资源,也可以使用apache的HttpClient,它是对HttpConnection的封装,使用更加简单。

3. 怎么解析Xml数据?
在Java中,解析Xml数据的方式很多,常用的几种方式:
(a). XML DOM
DOM 是W3C的标准,定义了访问HTML和XML文档的标准。
XML DOM 定义了所有 XML 元素的对象和属性,以及访问它们的方法(接口)。

(b). SAX
SAX是一个用于处理XML事件驱动的“推”模型,虽然它不是W3C标准,但它却是一个得到了广泛认可的API。SAX解析器不像DOM那样建立一个完整的文档树,而是在读取文档时激活一系列事件,这些事件被推给事件处理器,然后由事件处理器提供对文档内容的访问。SAX的工作原理简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。

(c).JDOM
JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。
JDOM是用Java语言读、写、操作XML的新API函数。在直接、简单和高效的前提下,这些API函数被最大限度的优化。

(d).DOM4J
dom4j是一个Java的XML API,类似于jdom,用来读写XML文件的。dom4j是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件,可以在SourceForge上找到它。在IBM developerWorks上面可以找到一篇文章,对主流的Java XML API进行的性能、功能和易用性的评测,dom4j无论在哪个方面都是非常出色的。如今你可以看到越来越多的Java软件都在使用dom4j来读写XML,特别值得一提的是连Sun的JAXM也在用dom4j。这是必须使用的jar包, Hibernate用它来读写配置文件。(摘自百度百科

综述,几种方式的比较(摘自java解析xml的4种经典方法):
1)DOM4J性能最好,连Sun的JAXM也在用DOM4J.目前许多开源项目中大量采用DOM4J,例如大名鼎鼎的Hibernate也用DOM4J来读取XML配置文件。如果不考虑可移植性,那就采用DOM4J.
2)JDOM和DOM在性能测试时表现不佳,在测试10M文档时内存溢出。在小文档情况下还值得考虑使用DOM和JDOM.虽然JDOM的开发者已经说明他们期望在正式发行版前专注性能问题,但是从性能观点来看,它确实没有值得推荐之处。另外,DOM仍是一个非常好的选择。DOM实现广泛应用于多种编程语言。它还是许多其它与XML相关的标准的基础,因为它正式获得W3C推荐(与基于非标准的Java模型相对),所以在某些类型的项目中可能也需要它(如在JavaScript中使用DOM)。
3)SAX表现较好,这要依赖于它特定的解析方式-事件驱动。一个SAX检测即将到来的XML流,但并没有载入到内存(当然当XML流被读入时,会有部分文档暂时隐藏在内存中)。

在了解以上的基本知识以后,就可以直接搞coding了。
我们使用Httpclient请求网络RSS资源,利用SAX解析RSS xml内容。
一、RSS源数据格式:
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>
	<channel>
		<title>A title</title>
		<link>http://rss.zhaopin.com</link>
		<item>
			<title>HR应是一场“春夜喜雨”</title>
			<link>http://marketing.hunteron.com/?p=876</link>
			<content:encoded>内容1</content:encoded>
			<slash:comments>0</slash:comments>
		</item>
		<item>
			<title>与高管面对面,你Hold住了吗?</title>
			<link>http://marketing.hunteron.com/?p=872</link>
			<content:encoded>内容2</content:encoded>
			<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

需要读取并保存<item>标签里面的<title>,<link>和<content:encoded>中的内容。

二、定义一个Model,封装RSS源数据中我们需要保存的节点。
/**
 * RSS 部分节点封装
 * 
 * @author boyce
 * @version 2013-12-27
 */
public class RssObject {
	private String title;
	private String link;
	private String content;

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getLink() {
		return link;
	}

	public void setLink(String link) {
		this.link = link;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public String toString() {
		return StringUtils.toString(this);
	}
}

三、实现一个HttpClientResponseHandler。关于HttpClientResponseHandler接口的定义。
/**
 * 继承SAX的DefaultHandler用于处理xml文件内容。
 * 实现HttpClientResponseHandler接口,处理HttpClient返回数据
 * @author boyce
 * @version 2014-1-24
 */
public class RssObjectHandler extends DefaultHandler implements HttpClientResponseHandler {
	/**
	 * 保存正在读取的标签名称
	 */
	private final static Stack<String> STACK = new Stack<String>();
	
	/**
	 * 保存HunteronObservation对象集合
	 */
	private final List<RssObject> RSS_OBJECTS = new ArrayList<RssObject>();
	
	private String title;
	private String link;
	private StringBuilder stringBuilder;
	private final static String ITEM = "item";
	private final static String TITLE = "title";
	private final static String LINK = "link";
	private final static String CONTENT = "content:encoded";
	
	//是否开始读取
	private boolean start = false;
	
	/**
	 * 处理HttpClient返回数据,由HttpClientRequest请求发送后调用,将HttpMethod传入获取ResponseBody
	 * @throws HttpClientException 
	 */
	public void handle(String response) throws HttpClientException {
		try {
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser parser = factory.newSAXParser();
			//SAX处理xml文本内容。将当前handler传入,由SAXParser回调
			parser.parse(new StringInputStream(response, "UTF-8"), this);
		} catch (Exception e) {
			throw new HttpClientException(e.getMessage());
		}
	}
	
	public List<RssObejct> getRssObejcts() {
		return RSS_OBJECTS;
	}
	
	/**
	 * 开始读取元素
	 */
	public void startElement(String uri, String localName, String qName,  
			Attributes attributes) throws SAXException  
	{  
		//遇到item标签,开始保存有效属性
		if (ITEM.equals(qName)) {
			start = true;
		}
		
		//保存当前读取的标签到栈顶
		if (start) {
			if (ITEM.equals(qName) || TITLE.equals(qName) ||
					LINK.equals(qName) || 
					CONTENT.equals(qName)) 
				STACK.push(qName);
		}
	}  
	
	/**
	 * 元素标签读取结束
	 */
	public void endElement(String uri, String localName, String qName)  
			throws SAXException  
	{  
		//弹出栈顶标签
		if (!STACK.isEmpty() && (ITEM.equals(qName) || TITLE.equals(qName) ||
				LINK.equals(qName) || 
				CONTENT.equals(qName)))
			STACK.pop();
		
		//如果一个item结束,保存一个HunteronObservation
		if (ITEM.equals(qName)) {
			RssObject rssObject = new RssObject();
			rssObject.setTitle(title);
			rssObject.setLink(link);
			rssObject.setContent(stringBuilder.substring(0, 
					(stringBuilder.length()<100?stringBuilder.length():100)).toString());
			stringBuilder = null;
			RSS_OBJECTS.add(rssObject);
		}
	} 
	
	/**
	 * 保存当前读取元素内的内容,注意,在读取某个标签大文本内容时,该方法不会一次性将大文本内容
	 * 全部传入,只会传入一定长度的char数组,然后多次调用该方法。
	 * 所以,对于大文本内容,需要每次调用改方法的时候先临时保存起来,将多次调用返回的char数组拼接起来
	 * 才是整个大文本内容的全部。例如将content保存在stringBuilder中。
	 * 在读取到结束标签后将stringBuilder中的内容取出并清空。
	 */
	public void characters(char[] ch, int start, int length) throws SAXException {
		if (!STACK.isEmpty()) {
			String qName = STACK.peek();
			//title
			if (TITLE.equals(qName))
				this.title = new String(ch, start, length);
			
			if (LINK.equals(qName))
				this.link = new String(ch, start, length);
			
			//保存content的txt文本前100个字符
			if (CONTENT.equals(qName)) {
				String htmlContent = new String(ch, start,length);
				String txtContent = Jsoup.parse(htmlContent).text();
				
				if (ObjectUtils.isNull(stringBuilder))
					stringBuilder = new StringBuilder();
				stringBuilder.append(txtContent);
			}
		}
	}
}


四、客户端使用场景:
// HttpClient
HttpClientRequest request = new HttpClientGetRequest("http://rss.source.com/?feed=rss2");

//创建HttpClientMethod的handler和SAX解析xml文件的handler
//RssObjectHandler 实现HttpClientResponseHandler 并继承SAX的DefaultHandler
RssObjectHandler handler = new RssObjectHandler();

//在request的process方法中调用HttpClientResponseHandler的handle(String response)方法,处理返回内容
//在handler的handle(..)方法中调用SAX接口处理xml数据,并将RssObjectHandler本身传给
//SAX的SAXParser的parse方法提供SAX回调(RssObjectHandler继承SAX的DefaultHandler)
request.process(handler);
List<RssObject> objs = handler.getRssObejcts();
System.out.println(objs);


总结:
我们在遇到一个问题的时候最好不要拿到一个API就用,或者上网搜一段代码贴上就用。
或许为了最快的解决问题这样的方式效率是高的,那么也要等空闲的时候好好整理自己的代码。作为程序员,代码使我们最亲密的伙伴,我还是觉得把它打扮的漂亮一点儿比较好。。。

我的博客很少会写一些拿来即用的东西,我觉得这没有多大的意义。
我希望的是大家或者包括以后的我自己看了这些博客后会有所悟,能真正从其中悟出东西来。

程序员最大的快乐莫过于发现自己每天都在成长。与君共勉。
普通程序员:解决问题。
文艺程序员:优雅的解决问题。
二逼程序员:没有。

写代码易,写优雅的代码不易,大家且写且珍惜吧。












3
0
分享到:
评论
1 楼 橙子hhh 2017-12-13  
哪有时间给你去研究!!!大神 你时间多

相关推荐

    移动RSS阅读器利用saxparser解析xml

    移动RSS阅读器是一种应用程序,它允许用户订阅并阅读XML格式的RSS(Really Simple Syndication)源,这是一种数据交换格式,广泛应用于博客、文章、新闻、音乐和视频网站,以提供实时更新的内容。RSS通过XML规范将...

    读取RSS-SAX解析XML实例(java版)

    在Java中,读取RSS数据首先需要获取RSS源的URL,然后使用XML解析器解析该URL的内容。这里采用的是SAX解析器,它通过触发一系列的事件(如开始文档、开始元素、结束元素等)来处理XML数据。以下是使用SAX解析XML的...

    java实现rss的发布和订阅

    RSS(Really Simple Syndication)是一种基于XML的网络内容聚合格式,它允许用户通过RSS阅读器或聚合器获取网站的更新信息,如新闻、博客文章等。在Java中实现RSS的发布和订阅,需要理解RSS的结构以及如何使用Java...

    Java使用SAX的rss解析实例

    3. **连接RSS源**:在Action类中,使用`java.net.URL`和`java.io.InputStream`打开并读取RSS链接。然后,创建一个`SAXParserFactory`,通过`newSAXParser`方法获取`SAXParser`,并调用`parse`方法,传入RSS输入流和...

    RSS阅读器(XML文件解析)

    在Rss_SAXParser这个项目中,开发者已经实现了一个完整的RSS阅读器,它展示了如何利用SAXParser解析RSS源并将其内容呈现给用户。通过阅读项目的源代码和博客解析,可以更深入地理解SAX解析XML的实际应用。此外,该...

    java Sax解析Xml

    调用`newInstance()`方法获取工厂实例,然后使用`newSAXParser()`方法创建解析器。 2. **设置事件处理器**: SAX解析器需要一个`DefaultHandler`或自定义的`ContentHandler`来处理解析过程中遇到的各种事件。这些...

    android_RSS经典开发教程

    首先需要从网络上获取RSS源的数据(通常为XML格式),然后使用DOM或SAX等方式解析这些数据。 2. **呈现RSS数据**:解析完成后,需要将数据以友好的形式展示给用户。这涉及到使用Android提供的GUI组件来设计用户界面...

    RSS 阅读器

    【RSS阅读器】是一种应用程序,它能够帮助用户订阅并管理RSS(Really Simple Syndication)源,从而方便地获取和阅读网络上的新闻、博客更新和其他在线内容。RSS是一种XML格式,用于发布和分享网站内容,使得用户...

    java实现天气预报(解释+源代码)

    本节将详细介绍如何使用Java SE中自带的JAXP(Java API for XML Processing)库来获取和解析Yahoo天气预报XML数据。 ##### 3.1 获取XML文档 使用Java的`HttpURLConnection`类来发送HTTP请求,并获取响应的XML文档...

    androidrssREADER

    【核心知识点5】网络请求:为了获取RSS源,程序可能使用了HttpURLConnection或OkHttp等库进行网络请求。在Android中,由于网络操作通常在主线程之外执行,所以可能运用了AsyncTask或者Retrofit等异步处理框架。 ...

    android xml 解析

    例如,在一个RSS阅读器应用中,我们可以使用SAX解析器读取RSS feed的XML内容,解析出文章标题、链接等信息,然后显示在列表中。 6. 总结 Android中的XML解析是移动开发中的重要技能。对于大型XML文件,SAX解析提供...

    安卓SAX解析xml

    - 获取`SAXParser`:通过工厂对象创建解析器。 - 设置`DefaultHandler`:将自定义处理器设置给解析器。 - 解析XML:调用解析器的`parse()`方法,传入XML文件输入流或路径。 3. **示例代码**: ```java public ...

    android-关于xml的解析

    通过自定义的事件处理器,开发者可以高效地解析XML并将其转化为Java对象,进一步供应用使用。 总结来说,XML在Android开发中扮演着重要角色,而SAX解析作为轻量级的解析方式,尤其适用于处理大型XML数据。理解XML的...

    android_sax_xml.zip_android_android sax

    - 使用`SAXParser`的`parse()`方法,传入XML输入源(如文件、流)和自定义的`DefaultHandler`实例来启动解析过程。 2. **关键回调方法** - `startDocument()`: 解析开始时调用。 - `endDocument()`: 解析结束时...

    详解android使用SAX解析XML文件

    2. 使用工厂创建SAXParser对象:`SAXParser parser = factory.newSAXParser();` 3. 获取XMLReader实例:`XMLReader reader = parser.getXMLReader();` 4. 实现ContentHandler接口并注册到XMLReader中,例如:`...

    android调用xml

    4. **解析XML数据**:如果XML文件包含数据,如RSS feed或网络响应,可以使用`XmlPullParser`或`SAXParser`进行解析。`XmlPullParser`是事件驱动的,逐个处理XML元素;而`SAXParser`采用推模型,适用于大文件解析。 ...

    AndroidRSSFeed-creatorb:如何在 android 上创建 rss 提要的教程,它是创建博客提要的简单实现,有许多文档可供学习

    3. **XML解析器**:项目可能包含一个XML解析器,如`SAXParser`或`DOMParser`,用于从网络加载现有的RSS feed,并将其转换为上述数据模型。 4. **XML生成器**:另一方面,我们需要一个机制将RSSFeed对象转换回XML格式...

    简单的rss阅读器

    这是一款简单的rss阅读器,用xml解析 package com.fenghuo.xml; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; ...

    XmlTest

    对于DOM解析,代码可能会使用如Java的`org.w3c.dom`包或Python的`xml.dom.minidom`库来实现。例如,读取XML文件的根元素,Java代码可能如下: ```java import javax.xml.parsers.DocumentBuilderFactory; import ...

    基于XML的数据处理基础支撑技术及应用论文

    Java 提供了丰富的库支持XML处理,如JAXB(Java Architecture for XML Binding)用于对象和XML之间的映射,DOM4J和JDom提供DOM解析的便利API,而SAXParser和XMLStreamReader是处理SAX解析的Java API。此外,Xalan和...

Global site tag (gtag.js) - Google Analytics