在asp.net站点中使用rss

    技术2022-05-20  42

     一、引言      近几年,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规范。为了提高响应速度,本文的示例中应用了缓存机制,但这样做会存在聚合列表更新比新闻发布时间稍迟的问题。


    最新回复(0)