一、引言
近几年,RSS的应用越来越广泛。新浪、新华网、网易等新闻门户网站及各个博客运营网站都推出了RSS订阅服务,Google也推出了Google Reader服务用来让用户定制自己所需的RSS源内容。RSS也被用于检索电子邮件,或通过复杂的工作流程传递交易信息等。RSS大有可能演变为所有信息(不论结构严谨或松散)的主要采集方式。
接下来我们将提供一套基于asp.net 2.0站点对RSS文件生成与调用的程序。
二、什么是RSS
RSS是一种XML表示数据的格式。通常用于共享标题和新闻文章的链接。这种格式可以包括标题、Url和描述等信息。
RSS起源于“网景通讯公司”的新闻频道语言,其目的是利用推(Push)的技术把用户订阅的新闻传送到订户。由于该技术没有找到合适商业模型和规范过于复杂,所以日渐衰落。但到了近些年由于网络日志(Web Blog)的流行,RSS也逐渐成为描述Blog主题和更新信息的最基本方法。为了适应新的网络应用需要,UserLand公司把RSS从网景公司原来的0.9版升级到了0.91版、0.92版,随后在各种Blog工具中得到了应用,并被众多的专业新闻站点所支持。在广泛的应用过程中,一个联合小组根据W3C新一代的语义网技术RDF对RSS进行了重新标准化定义,发布RSS 1.0,并希望能把RSS发展成为一个通用的规范。但直到今天,RSS 1.0也没有成为标准化组织的真正标准。2002年9月UserLand公司(一家著名的博客公司)独自把RSS由原来的0.94版升级到了全新模式的2.0版本,该版本与0.9x版本是兼容的,但不兼容于RSS 1.0版。RSS也分化形成了RSS 0.9x/2.0和RSS 1.0两个阵营。由于RSS 0.9x/2.0应用起来更加简单实用,所以该规范得到广泛的使用。本文也主要基于RSS2.0规范上使用的。
为网站创建RSS,必须对RSS了解。RSS文件主要是由一个<channel>元素及其子元素组成的。RSS2.0 的根元素是<rss>元素,这个元素可以有一个版本号的属性。<rss>元素只有一个子元素<channel>用来描述频道聚合的内容。<channel>还包含表示对频道本身的描述,如<title>表示频道或提要的名称、<link>表示与频道关联的Web站点或站点区域、<description>表示该频道的描述信息等。项<item>通常是频道的主要部分。项通常包含下列元素:
<title>:项的名称。在应用中被转换成Html的标题。
<link>:项的URL。指向title的链接。
<description>:内容描述。指向URL的摘要或补充。
<author>:作者的信息。
<category>:组织分类。
<comments>:关于项注释页的URL。
<enclosure>:支持与该项有关的媒体对象。
<guid>:唯一与该项有关的永久链接。
<pudDate>:该项的发布时间。该日期必须按照 RFC822 日期和时间规范显示。
<source>:该项来自哪个频道。
所有的项元素都是可选的,但是一个项中必须包含一个<title>元素或<description>元素。
三、在asp.net 2.0中生成RSS规范的页面
因为在RSS文件中包含若干个项(RSS 0.9x中最多为15个),所以采用数据绑定的方法来实现来会更为方便。由于Repeater控件自定义性非常强,并且该控件对服务器的性能消耗也很小,在页面上显示也不会产生冗余的Html代码,所以我们使用Repeater控件来进行数据绑定。
RSS.aspx页面代码:
<%@ Page Language="C#" AutoEventWireup="true" ContentType="text/xml" CodeFile="Rss.aspx.cs" Inherits="NewsRss" ValidateRequest="false"EnableViewState="false" ResponseEncoding="UTF-8" StylesheetTheme=""Theme=""%>
<asp:Repeater ID="RptRSS" runat="server">
<HeaderTemplate>
<rss version="2.0">
<channel>
<title>新闻</title>
<link>http://localhost/news/</link>
<description>信息网新闻排行</description>
</HeaderTemplate>
<ItemTemplate>
<item>
<title><%#Output(Eval("Title")) %></title>
<link><%#Eval("NewsUrl") %></link>
<pubDate><%#Convert.ToDateTime(Eval("ApprovedDate").ToString()).ToString("r") %></pubDate>
<description><%#Output(Eval("Abstract"))%></description>
<author><%#Output(Eval("PostUser"))%></author>
</item>
</ItemTemplate>
<FooterTemplate>
</channel>
</rss>
</FooterTemplate>
</asp:Repeater>
为了满足RSS2.0规范,所以必须要在页面上去掉了一些诸如<html>、<head>、<body>、<form>等Html代码。以下是部分代码的说明:
ContentType="text/xml" 指输出的是XML格式。
ResponseEncoding="UTF-8" 参数设置能使XML支持中文显示。
如果站点使用了主题和皮肤,则需要设置StylesheetTheme=""Theme=""。
Output函数是将非法的 xml 字符替换为它们对应的合法的转义字符,函数是在后台代码中声明的,后面再详细说明。
<pubDate>元素中的ToString("r")是把ApprovedDate格式化为RFC822 日期和时间规范(例如:Thu, 01 Dec 2005 21:35:55 GMT)。
注意:XML格式是大小写敏感的,这就意味着,XML元素的起始和终止标签必须匹配,拼写和大小写都必须一致。
后台代码Rss.aspx.cs如下:
private const string connectionString = @"数据库链接字符串";
public partial class NewsRss : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
DataTable dt = GetNewsRss();
DataView myDV = dt.DefaultView;
RptRSS.DataSource = myDV;
RptRSS.DataBind();
}
}
private DataTable GetNewsRss()
{
DataTable dt = (DataTable)Cache["NewsRssCache"];
if (dt == null)
{
SqlConnection connection = new SqlConnection(connectionString);
SqlCommand command = new SqlCommand("SELECT TOP 15 Title, PostUser, LEFT(CAST(Body AS varchar(1000)), 350)+ '...' AS Abstract, 'http://localhost/news/VIEW.aspx?newsID=' +CAST(NewsID AS varchar(6)) AS NewsUrl FROM News_News WHERE (Approved = 1) ORDER BY ApprovedDate DESC ", connection);
command.CommandType = CommandType.Text;
SqlDataAdapter da = new SqlDataAdapter(command);
dt = new DataTable();
try
{
connection.Open();
da.Fill(dt);
Cache.Insert("NewsRssCache", dt, null, DateTime.Now.AddMinutes(10), TimeSpan.Zero);
}
finally
{
connection.Dispose();
command.Dispose();
da.Dispose();
}
}
return dt;
}
protected string Output(object inputString)
{
if (inputString == null)
return string.Empty;
StringBuilder strBuilder = new StringBuilder();
string strTemp = HttpContext.Current.Server.HtmlEncode(inputString.ToString());
strBuilder.Insert(0, strTemp);
strBuilder.Replace(((char)32).ToString(), " ");
strBuilder.Replace(((char)9).ToString(), " ");
strBuilder.Replace(((char)34).ToString(), """);
strBuilder.Replace(((char)38).ToString(), "&");
strBuilder.Replace(((char)39).ToString(), "'");
strBuilder.Replace(((char)60).ToString(), "<");
strBuilder.Replace(((char)62).ToString(), ">");
strBuilder.Replace(((char)13).ToString(), " ");
return strBuilder.ToString();
}
为了加快页面浏览速度和提高服务器性能,我们采用了缓存机制。GetNewsRss()是返回缓存中NewsRssCache的表数据。如果缓存中没有该表则创建它,该表在服务器缓存中的生存期设置为10分钟。
Output函数是把数据字符格式化为XML数据显示。也就是把<,>,&,", (空格)和'转换成<,>,& ,", 和'。该函数用于在页面上XML数据格式的输出。
这样生成的Rrs.aspx页面就可以用SharpReader、SSReader、NewzCrawler等RSS阅览器订阅浏览,也可以被其他站点调用了。
四、在asp.net 2.0站点中调用RSS 2.0规范的数据
当然也可以让我们的asp.net站点来调用其它站点的RSS数据,我们可以这样做。
在项目管理器中添加名称为App_Code的Asp.net文件夹,并在文件夹中分别添加RssFeed.cs,RssChannel.cs,RssItem.cs,IItem.cs,ItemListView.cs类文件。新建UserControls文件夹,在文件夹中添加名为RssItemsList的用户控件。(如图所示)
C#2.0中增加了一个激动人心的特征是泛型的使用。泛型提供了类型安全,并且能对参数的类型施加约束。所以我们采用泛型的方法来撷取调用调用RSS文件中的项元素内容。
由于.NET 2.0的System.Collections.Generics 命名空间包含了泛型集合定义,各种不同的集合/容器类都已经被"参数化"了,所以在我们的程序中需要引用(using)该命名空间。
RssItem.cs是从RSS 2.0的Xml文档中提取一个元素构建成为的类。文件代码:
namespace NewsRss.WebModules.Business.Rss
{
public class RssItem : IItem
{
private readonly string title;
private readonly string description;
private readonly string link;
public string Title { get { return title; } }
public string Description { get { return description; } }
public string Link { get { return link; } }
internal RssItem(XmlNode itemNode)
{
XmlNode selected;
selected = itemNode.SelectSingleNode("title");
if (selected != null)
title = selected.InnerText;
selected = itemNode.SelectSingleNode("description");
if (selected != null)
description = selected.InnerText;
selected = itemNode.SelectSingleNode("link");
if (selected != null)
link = selected.InnerText;
}
RssChannel.cs是从RSS 2.0的Xml文档中提取<channel>元素构建成为的类。文件代码:
namespace NewsRss.WebModules.Rss
{
public class RssChannel
{
private readonly string title;
private readonly string link;
private List<RssItem> items;
public string Title { get { return title; } }
public string Link { get { return link; } }
public IList<RssItem> Items { get { return items.AsReadOnly(); } }
internal RssChannel(XmlNode channelNode)
{
items = new List<RssItem>();
title = channelNode.SelectSingleNode("title").InnerText;
link = channelNode.SelectSingleNode("link").InnerText;
XmlNodeList itemNodes = channelNode.SelectNodes("item");
foreach (XmlNode itemNode in itemNodes)
{
items.Add(new RssItem(itemNode));
}
}
RssFeed.cs用来读取和格式化Rss 2.0的XML文件,采用工厂模式来构建。文件代码:
namespace NewsRss.WebModules.Rss
{
public class RssFeed
{
private List<RssChannel> channels;
public IList<RssChannel> Channels { get { return channels.AsReadOnly(); } }
public RssChannel MainChannel { get { return Channels[0]; } }
private RssFeed(XmlNode xmlNode)
{
channels = new List<RssChannel>();
// 读取<rss>标记
XmlNode rssNode = xmlNode.SelectSingleNode("rss");
// 在<rss>中遍历 <channel>节
XmlNodeList channelNodes = rssNode.ChildNodes;
foreach (XmlNode channelNode in channelNodes)
{
RssChannel newChannel = new RssChannel(channelNode);
channels.Add(newChannel);
}
}
public static RssFeed FromUrl(string url)
{
XmlTextReader reader = new XmlTextReader(url);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(reader);
return new RssFeed(xmlDoc);
}
}
}
IItem.cs在此接口类中,声明了两个只读属性Description和Title。文件代码:
namespace NewsRss.WebModules.Rss
{
public interface IItem
{
string Description { get; }
string Title { get; }
}
}
ItemListView.cs取得项列表。文件代码:
namespace NewsRss.WebModules.Rss
{
public class ItemListView<T> : IDisposable where T : IItem
{
private string title;
private int selectedIndex = 0;
private IList<T> items;
private int maxItemsToShow;
public int NumItemToShow { get { return Math.Min(items.Count, maxItemsToShow); } }
public int MaxItemsToShow { get { return maxItemsToShow; } set { maxItemsToShow = value; } }
public int SelectedIndex { get { return selectedIndex; } }
public T SelectedItem { get { return items[selectedIndex]; } }
public void NextArticle()
{
if (selectedIndex < NumItemToShow - 1)
selectedIndex++;
else
selectedIndex = 0;
}
public ItemListView(string title, IList<T> items)
{
if (items == null)
throw new ArgumentException("项不能为空", "items");
this.items = items;
this.title = title;
}
public void Dispose()
{}
}
}
RssItemsList.ascx用户控件代码如下:
<%@ OutputCache Duration="600" VaryByParam="none" %>
<table border="1"cellpadding="0"
cellspacing="0" style=" border-color:#3366cc" width="100%">
<tr>
<tdstyle="background-color:#3366cc; border-color:#3366cc;" >
<asp:Label ID="RssTitle" runat="server" ForeColor="White"></asp:Label></td>
</tr>
<tr>
<td>
<asp:Literal ID="RssItems" runat="server"></asp:Literal></td>
</tr>
</table>
为了提高浏览速度,所以把控件的缓存设置为600秒。
RssItemsList.ascx用户控件的后台代码:
private RssFeed rssFeed;
private ItemListView<RssItem> rssView;
private int itemsCount=15;
private string rssUrl="";
public int ItemsCount{get{ return itemsCount; } set{ itemsCount = value;}}
public string RssUrl{get{return rssUrl;} set{rssUrl=value;}}
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
if (LoadRssFeed(RssUrl))
{
rssView = new ItemListView<RssItem>(rssFeed.MainChannel.Title, rssFeed.MainChannel.Items);
RssTitle.Text = rssFeed.MainChannel.Title;
rssView.MaxItemsToShow = ItemsCount;
RssItems.Text = "";
for (int i = 0; i < rssView.NumItemToShow; i++)
{
RssItems.Text += "<a href='" + rssView.SelectedItem.Link +"' target='_blank'>" + rssView.SelectedItem.Title + "</a><br>";
rssView.NextArticle();
}
else
{
RssItems.Text = "RSS Feed 源数据出错!";
}}
private bool LoadRssFeed(string url)
{
try
{
rssFeed = RssFeed.FromUrl(url);
return true;
}
catch
{
return false;
}
}
LoadRssFeed函数是调用RssFeed类的FromUrl方法,用来判断RSS Feed的格式是否正确。如果正确,就把文件格式化为我们所需的格式。
在RssItemsList用户控件中,定义了两个属性,其中RssUrl属性用来设置RSS文件的Url地址,ItemsCount属性用来设置显示RSS项的个数。
在页面上调用RssItemsList控件的代码:
<uc1:RssItemsList id="RssItemsList1" ItemsCount=10 RssUrl="http://127.0.0.1/news/rss.aspx" runat="server"> </uc1:RssItemsList>
这样,一个完整的RSS Feed调用实例就完成了。把本控件与用户的cookies联系起来可以实现用户自定义定制RSS源,类似于一些网站提供的用户自定义RSS博览服务。
五、总结
RSS提供了一种网站与其他站点之间共享内容的一种简易方式(也叫聚合内容)。本文通过对RSS规范的简单分析,并在此基础上实现asp.net对RSS文件的生成和调用。这样我们可以把自己站点内容更为广泛的共享,又可以对支持RSS的站点进行调用显示在自己的站点上。
但是由于RSS feed规范标准不是统一的,会为我们的调用带来了相当大的麻烦,本文中只支持RSS 0.9x/2.0规范。为了提高响应速度,本文的示例中应用了缓存机制,但这样做会存在聚合列表更新比新闻发布时间稍迟的问题。
在asp.net站点中使用rss
最新推荐文章于 2017-02-09 18:00:37 发布