转载请注明出处。
在本文开始之前,我们首先有必要了解一下什么是RSS,以及RSS的使用规则。
第一节 RSS 2.0规范
本节来源:http://blogs.law.harvard.edu/tech/rss
译文来源:http://tonyqus.cnblogs.com/archive/2005/01/30/93684.aspx
什么是RSS?
RSS是一种网页内容联合格式(web content sydication format)。
它的名字是Really Simple Syndication的缩写。
RSS是XML的一种。所有的RSS文档都遵循XML 1.0规范,该规范发布在W3C网站上。
在一个RSS文档的开头是一个<rss>节点和一个规定的属性version,该属性规定了该文档将以RSS的哪个版本表示。如果该文档以这个规范来表示,那么它的version属性就必须等于2.0。
在<rss>节点的下一级是一个独立的<channel>节点,该节点包含关于channel的信息和内容。
关于本文档
本文档属于RSS版本为2.0.1。
必需的频道节点
下面有一份必须包含的频道(channel)节点的列表,每一个都有一个简单的描述、一个例子、应该出现的位置和更详细描述的超链接(以http://www.ppurl.com/feed为例)。
元素 |
描述 |
范例 |
title |
频道(channel)名称。它可以告诉别人如何访问你的服务。如果你有一个与你的RSS文件内容一致的HTML网站,你的title元素值应该与你的网站的标题相同。 |
皮皮书屋 |
link |
响应该频道的网站的URL |
http://www.ppurl.com |
description |
关于该频道的描述 |
这里只有一些还不错的电子书。 |
可选的频道元素
下面是可选的频道元素(channel)中可以包含的元素列表 :
节点 |
描述 |
范例 |
language |
使用的语言。这允许聚合器对所有的意大利语站点分组。 |
en-us |
copyright |
版权声明 |
Copyright 2002, Spartanburg Herald-Journal |
managingEditor |
内容负责人的Email |
[email protected] (George Matesky) |
webMaster |
技术人员的Email |
[email protected] (Betty Guernsey) |
pubDate |
内容的发布时间 |
Sat, 07 Sep 2002 00:00:01 GMT |
lastBuildDate |
最后更新时间 |
Sat, 07 Sep 2002 09:42:31 GMT |
category |
指定该频道所属的一个或多个分类。遵循与item级category元素相同的规则。 |
<category>Newspapers</category> |
generator |
生成该频道的程序名称 |
MightyInHouse Content System v2.3 |
docs |
指向rss格式文档的url地址? |
http://blogs.law.harvard.edu/tech/rss |
cloud |
允许所有进程注册一个cloud用于获得频道的更新通知,并为rss种子实现一个轻量级的发布订阅协议。 |
<cloud domain="rpc.sys.com" port="80" path="/RPC2" registerProcedure="pingMe" protocol="soap"/> |
ttl |
ttl是Time to live的缩写。它指示cache的有效保存时间。 |
<ttl>60</ttl> |
image |
与频道一起显示的图片地址 |
|
rating |
该频道的统计图片地址 |
|
textInput |
指定一个textbox与该频道一起显示 |
|
skipHours |
告诉使用者哪些时段是可以忽略的 |
|
skipDays |
告诉使用着哪些天是可以忽略的 |
以下是频道(channel)元素中几个常用子节点的说明:
<channel>子节点<image>
l <image>是一个可选的<channel>子节点,该节点包含三个必需的子元素和三个可选的子元素。
l <url>是GIF、JPEG或PNG图像文件的URL地址,该图像代表整个频道 。
l <title>用于描述上面的图像,等同于HTML语言中的<img>的alt属性 。
l <link>是要连接的站点的url,当显示频道时,图像的连接指向该站点。
l <title>和<link>应该与频道的<title>和<link>有相同的值。
l 可选的节点包括<width>和<height>,它们是数字类型,指定图像的宽度和高度,单位为像素。
l <description>就是link的TITLE属性中文本,它将在调用网页时显示出来。
备注:
图像宽度的最大值为144,默认值为88
图像高度的最大值为400,默认值为31
<channel>子节点<cloud>
<cloud>是一个可选的<channel>子节点。
它指定一个可以支持rssCloud接口的web服务,rssCloud接口可以用HTTP-POST,XML-RPC或SOAP1.1实现。
它的目的是允许通知注册为cloud的进程频道被更新,从而实现一个轻量级的发布订阅协议。
<cloud domain="rpc.sys.com" port="80" path="/RPC2" registerProcedure= "myCloud.rssPleaseNotify" protocol="xml-rpc" />
在这个例子中,为了请求频道通知,你需要发送一个XML-RPC消息到rpc.sys.com的80端口,路径为/RPC2。调用的过程为myCloud.rssPleaseNotify。
<channel>子节点<ttl>
<ttl>是一个可选的<channel>子节点。
ttl是time to live的缩写。它表示频道在被刷新前应该被缓存的时间。这使得rss源可以被一个支持文件共享的网络所管理,例如Gnutella
例如:<ttl>60</ttl>
<channel>子节点<textInput>
<textInput>是<channel>的可选的子节点,<textInput>包含四个子节点:
l <title>是提交按钮的标签。
l <description>是该文本输入区的描述。
l <name>是文本输入区的名称。
l <link>是处理文本输入的CGI脚本的URL。
使用<textInput>的目的有些神秘。你可以用它提供一个搜索引擎输入框,或让读者提供反馈信息。许多聚合器忽略该节点。
<item>的节点
一个频道可以包含许多项目(item)节点。一个项目可以代表一个故事——比如说一份报纸或杂志上的故事,如果是这样的话,那么项目的描述则是故事的概要,项目的链接则指向整个故事的存放位置。项目的所有节点都是可选的,但是至少要包含至少一个标题(title)和描述 (description)。以下是项目(item)节点中可以包含的元素列表 :
节点 |
描述 |
范例 |
title |
item的标题 |
Venice Film Festival Tries to Quit Sinking |
link |
item的URL |
http://www.nytimes.com/2002/09/07/movies/07FEST.html |
description |
item概要 |
Some of the most heated chatter at the Venice Film Festival this week was about the way that the arrival of the stars at the Palazzo del Cinema was being staged. |
author |
作者的email地址 |
|
category |
item可以包含在一个或多个分类中 |
Simpsons Characters |
comments |
与item相关的评论的地址 |
http://www.myblog.org/cgi-local/mt/mt-comments.cgi?entry_id=290 |
enclosure |
附加的媒体对象 |
|
guid |
可以唯一确定item的字符串 |
http://inessential.com/2002/09/01.php#a2 |
pubDate |
item发布的时间 |
Sun, 19 May 2002 15:21:36 GMT |
source |
rss频道来源 |
Quotes of the Day |
以下是频道元素(channel)中几个常用子节点的说明:
<item>子节点<source>
<source>是<item>的可选节点。
它的值是item来自的rss频道的名称,从item的title衍生而来。它有一个必须包含的属性url, 该属性链接到XML序列化源。
<source url="http://static.userland.com/tomalak/links2.xml">Tomalak's Realm</source>
该节点的作用是提高连接的声望,进一步推广新闻项目的源头。它可以用在聚合器的Post命令中。当从聚合器通过webblog访问一个item时,<source>能够自动被生成。
<item>子节点<enclosure>
<enclosure>是<item>的可选节点。
它有三个必要的属性。url属性指示enclosure的位置,length指出它的字节大小,type属性指出它的标准MIME类型。
url必须为一个http url。
<enclosure url="http://www.scripting.com/mp3s/weatherReportSuite.mp3" length="12216320" type="audio/mpeg" />
<item>子节点<category>
<category>是<item>的可选节点。
它有一个可选属性或域,该属性是一个用来定义分类法的字符串。
该节点的值是一个正斜杠分割的字符串,它用来在指定的分类法中识别一个分级位置(hierarchic location)。处理器可以为分类的识别建立会话。(Processors may establish conventions for the interpretation of categories)下面有两个例子:
<category>Grateful Dead</category>
<category domain="http://www.fool.com/cusips">MSFT</category>
你可以根据你的需要为不同的域(domain)包含很多category节点,并且可以在相同域的不同部分拥有一个前后参照的item。
<item>子节点<pubDate>
<pubDate>是<item>的可选节点。
它的值是item发布的日期。如果它是一个没有到达的日期,聚合器在日期到达之前可以选择不显示该item。
<pubDate>Sun, 19 May 2002 15:21:36 GMT</pubDate>
<item>子节点<guid>
<guid>是<item>的可选节点。
guid是globally unique identifier的缩写。它是一个可以唯一识别item的字符串。当item发布之后,聚合器可以选择使用该字符串判断该item是否是新的。
<guid>http://some.server.com/weblogItem3207</guid>
guid没有特定的语法规则,聚合器必须将他们看作一个字符串。生成具有唯一性的字符串guid取决于种子的源头。
如果guid节点有isPermaLink属性,并且值为真,读取器就会认为它是item的permalink。permalink是一个可在web浏览器中打开的url链接,它指向<item>节点所描述的全部item。
<guid isPermaLink="true">http://inessential.com/2002/09/01.php#a2</guid>
isPermaLink是可选属性,默认值为真。如果值为假,guid将不会被认为是一个url或指向任何对象的url。
<item>子节点<comment>
<comment>是<item>的可选节点。
如果出现,它指向该item评论的url:
<comments>http://rateyourmusic.com/yaccs/commentsn/blogId=705245&itemId=271</comments>
<item>子节点<author>
<author>是<item>的可选节点。
它是item的作者的email。对于通过rss传播的报纸和杂志,作者可能是写该item所描述的文章的人。主要应用于webblogs(博客、论坛等),因为内容的作者很可能不是责任编辑或站长。对于个人维护的webblog,可忽略<author>节点。 以下是author节点的使用范例:
<author>[email protected] (Lawyer Boyer)</author>
第二节 .NET对读取RSS的支持
在.NET Framework 3.5中,引入了SyndicationFeed类,它用于解析RSS源的xml文件,并包装成一个实体类方便我们的使用。
需要注意的是,如果要使用SyndicationFeed类,要首先using System.ServiceModel.Syndication命名空间,此命名空间包含在System.ServiceModel.Web引用中,此引用包含在System.ServiceModel.Web.dll文件中。
以下贴出MSDN对SyndicationFeed类的说明:
序列化为 RSS 2.0 时,会将 SyndicationFeed 实例写入 <rss> 元素中。 下表显示如何将 SyndicationFeed 类中定义的每个属性序列化为 RSS 2.0。
SyndicationFeed 属性 |
序列化形式 |
AttributeExtensions |
集合中每个属性的 <channel> 元素中的属性。 |
Authors |
如果集合中只有一个 SyndicationPerson,则为 <managingEditor> 元素;否则为集合中每个 SyndicationPerson 的 <a10:author> 元素。 |
Categories |
集合中每个 SyndicationCategory 的 <category> 元素。 |
Contributors |
集合中每个 SyndicationPerson 的 <a10:contributor> 元素。 |
Copyright |
一个 <copyright> 元素。 |
Description |
一个 <description> 元素。 |
ElementExtensions |
集合中的每个元素都会写入 <channel> 元素中。 |
Generator |
一个 <generator> 元素。 |
Id |
一个 <a10:id> 元素。 |
ImageUri |
一个 <image> 元素。 |
Items |
集合中每个 SyndicationItem 的 <item> 元素。 |
Language |
一个 <language> 元素。 |
LastUpdatedTime |
一个 <lastBuildDate> 元素。 |
Links |
集合中每个 SyndicationLink 的 <a10:link> 元素。 |
Title |
一个 <title> 元素。窗体底端 |
以下着重介绍一下Items属性中(它是一个SyndicationItem集合),每个SyndicationItem对象包含的属性:
序列化为 RSS 2.0 时,会将 SyndicationItem 实例写入 <item> 元素中。 下表演示如何将所定义的每个 SyndicationItem 属性序列化为 RSS 2.0。
SyndicationItem 属性 |
序列化形式 |
AttributeExtensions |
<item> 元素中的属性。 |
如果 Authors 集合中只有一个 SyndicationPerson,则为 <managingEditor>;否则为集合中每个作者的 <a10:author> 元素。 |
|
一个 <category> 元素。 |
|
一个 <a10:content> 元素。 |
|
Contributors 集合中每个 SyndicationPerson 的 <a10:contributor> 元素。 |
|
一个 <copyright> 元素。 |
|
<item> 元素中的元素。 |
|
一个 <a10:id> 元素。 |
|
一个 <a10:updated> 元素。 |
|
Links 集合中每个 SyndicationLink 的 <link> 元素。 |
|
一个 <pubDate> 元素。 |
|
一个 <source> 元素。 |
|
一个 <description> 元素。 |
|
一个 <title> 元素。窗体底端 |
我们贴心的微微真是面面俱到……这样一来我们省去了自己写foreach封装实体的过程,我们只需要提供RSS的xml文件即可调用各种属性、方法来完成我们的功能。
以下写了一个简单的实例,以展示如何加载RSS的xml文件,并在页面中展示其内容:
<asp:Repeater ID="Repeater1" runat="server"> <ItemTemplate> <div><a href="<%#Eval("Links[0].Uri.AbsoluteUri")%>"><%#Eval("Title.Text")%></a></div> <div><%#Eval("Summary.Text")%></div> <hr /> </ItemTemplate> </asp:Repeater> |
上述代码以一个Repeater控件展示了订阅内容的标题、内容概述,并且点击标题可打开内容链接。
以下是后台代码,其展示了如何加载RSS的xml文件,并绑定到Repeater控件的数据源(DataSource)中:
//发起一个请求 WebRequest request = WebRequest.Create("http://www.ppurl.com/feed"); //获得一个响应 WebResponse response = request.GetResponse(); //从响应中获取的数据流创建一个XmlReader实例 XmlReader reader = XmlReader.Create(response.GetResponseStream()); //使用XmlReader实例加载一个SyndicationFeed实例 SyndicationFeed feed = SyndicationFeed.Load(reader); //绑定数据源 Repeater1.DataSource = feed.Items; Repeater1.DataBind(); |
运行此实例,可以看到如下页面:
以上即是.NET对读取RSS的支持,下一节将介绍使用linq to xml来快速创建RSS。
第三节 使用linq to xml 快速创建RSS
首先,介绍一下本示例所使用的内容表:
字段 |
类型 |
说明 |
ContentID |
int |
内容ID |
Title |
nvarchar(50) |
标题 |
[Content] |
ntext |
内容正文 |
ContentOverview |
varchar(7000) |
内容概述 |
AddDate |
smalldatetime |
发布日期 |
EditDate |
smalldatetime |
编辑日期 |
Status |
bit |
启用状态 |
UserID |
int |
作者ID |
然后,创建一下linq to sql类,加载这个表。创建的linq to sql类我们命名为SunnyCoder.dbml,实例类型为SunnyCoderDataContext。
下面需要创建rss.aspx页面。创建页面以后,将@Page指令以外的html元素全部删除,操作完成后的页面代码将只留下以下代码:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="rss.aspx.cs" Inherits="rss" %> |
然后,需要在页面的Page_Load事件中写入以下代码:
using (SunnyCoderDataContext db = new SunnyCoderDataContext()) { //读取需要加载的文章对象(linq to sql) var contents = db.Contents.Where(c => c.Status).OrderByDescending(c => c.AddDate); //创建rss的xml文件 XElement contacts = new XElement ( "rss" , new XAttribute("version", "2.0") , new XElement ( "channel" , new XElement("title", "欢迎订阅SunnyWay") , new XElement("link", "http://www.sunnycoder.cn") , new XElement("description", "程序员自己的故事") , new XElement("language", "zh_cn") , new XElement("copyright", "Copyright 2008 sunnycoder") , new XElement("webMaster", "[email protected]") ) ); //创建rss的item项 foreach (var c in contents) { contacts.Element("channel").Add ( new XElement ( "item" , new XElement("title", c.Title) , new XElement("link", String.Format("http://www.sunnycoder.cn/Document/DocumentDetails.aspx?contentid={0}", c.ContentID)) , new XElement("description", c.ContentOverview) , new XElement("pubDate", c.AddDate) ) ); } //设置输出流的HTTP MIME类型 Response.ContentType = "text/xml"; //输入xml文件 using (XmlWriter writer = new XmlTextWriter(Response.OutputStream, Encoding.UTF8)) { contacts.WriteTo(writer); } } |
运行上述代码,可得到以下结果:
<rss version="2.0"> <channel> <title>欢迎订阅SunnyWay</title> <link>http://www.sunnycoder.cn</link> <description>程序员自己的故事</description> <language>zh_cn</language> <copyright>Copyright 2008 sunnycoder</copyright> <webMaster>[email protected]</webMaster> <item> <title>ASP.NET跨页面传值技巧总结</title> <link>http://www.sunnycoder.cn/Document/DocumentDetails.aspx?contentid=4</link> <description>关于页面传值的方法,引发了很多讨论。看来有很多人关注这个,我就我个人观点做了些总结,希望对大家有所帮助。 1. 使用QueryString变量QueryString是一种非常简单的传值方式,他可以将传送的值显示在浏览器的地址栏中。如果是传递一个或多个安全性要求不高或是结构简单的数值时,可以使用这个方法。但是对于传递数组或对象的话,就不能用这个方法了。下面是一个例子:a.aspx的C#代码priva...</description> <pubDate>2009-11-21T01:24:00</pubDate> </item> <item> <title> JQuery技巧总结</title> <link>http://www.sunnycoder.cn/Document/DocumentDetails.aspx?contentid=3</link> <description>jquery技巧总结一、简介1.1、概述随着WEB2.0及ajax思想在互联网上的快速发展传播,陆续出现了一些优秀的Js框架,其中比较著名的有Prototype、YUI、jQuery、mootools、Bindows以及国内的JSVM框架等,通过将这些JS框架应用到我们的项目中能够使程序员从设计和书写繁杂的JS应用中解脱出来,将关注点转向功能需求而非实现细节上,从而提高项目的开发速度。jQuery...</description> <pubDate>2009-11-21T01:15:00</pubDate> </item> <item> <title>Spring.Net的基本使用</title> <link>http://www.sunnycoder.cn/Document/DocumentDetails.aspx?contentid=2</link> <description>本文将按B/S与C/S结构介绍Spring.Net的基本使用方法。B/S结构下:1、配置web.config 2、aspx页面 3、接口 4、实现类。C/S结构下1、配置App.config 2、调用</description> <pubDate>2009-11-15T23:39:00</pubDate> </item> <item> <title>Log4Net使用指南</title> <link>http://www.sunnycoder.cn/Document/DocumentDetails.aspx?contentid=1</link> <description>声明:本文内容主要译自Nauman Leghari的Using log4net,亦加入了个人的一点心得(节3.1.4)。请在这里下载示例代码 1 简介 1.1 Log4net的优点:几乎所有的大型应用都会有自己的用于跟踪调试的API。因为一旦程序被部署以后,就不太可能再利用专门的调试工具了。然而一个管理员可能需要有一套强大的日志系统来诊断和修复配置上的问题。 经验表明,日志记录往往是软件开发周期...</description> <pubDate>2009-11-15T12:40:00</pubDate> </item> </channel> </rss> |
总结:
经过三节文章的介绍,RSS的原理、规范格式、读取和生成都已经介绍完了,希望对大家的工作有所帮助。转载请注明出处。