在asp.net站点中使用rss

 一、引言
  
  近几年,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数据显示。也就是把<,>,&,", (空格)和'转换成<,>,& ,", 和&apos;。该函数用于在页面上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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值