在Web站點中創建和使用Rss源

 術語表

tag:標籤
markup:標記
node:結點
item:條目
entry:入口
Rss Reed:Rss 源

介紹

Rss是將你Web站點的內容與其他人分享的標準方式。Rss代表着:Really Simple Syndication。它不過是一個標準化的XML標記,用於描述你想要分享的內容。因此Rss是一個在你的內容準備好被其他用戶所消費時被廣泛接受的格式。一些使用Rss的範例站點有:www.asp.netweblogs.asp.net 和 www.dotnetbips.com 。Dotnetbips.com 通過 Rss 發佈新添內容的列表,這個列表可能會被其他的站長放置在他們的站點或目錄中。

Rss的格式

如同我之前提到的,Rss不過是有着一些特殊標籤的XML標記。下面的標記展示了這樣一個文檔:

<rss version="2.0">
    <channel>
    <title>DotNetBips.com Latest Articles</title> 
    <link>www.dotnetbips.com</link> 
    <description>DotNetBips.com Latest Articles</description> 
    <copyright>Copyright (C) DotNetBips.com. All rights reserved.</copyright> 
    <generator>www.dotnetbips.com RSS Generator</generator> 
    <item>
    <author>Bipin Joshi</author>
    <title>Using WebRequest and WebResponse</title> 
    <link>http://www.dotnetbips.com/displayarticle.aspx?id=239</link> 
    <description>Description here</description> 
    <pubDate>Sun, 25 Jan 2004 12:00:00 AM GMT</pubDate> 
    </item>
    </channel>
</rss>

讓我們仔細看看每一個標記:

  • <rss>:根結點,擁有一個version(版本)屬性,最新版本是 2.0
  • <channel>:rss下的根結點,可以再次包含<channel>結點。<channel>結點可以進一步包含<title>,<link>,<item>結點。
  • <title>:代表Rss源的標題。
  • <link>:代表着提供Rss源的站點的URL。
  • <description>:關於這個Rss源的更多詳細信息。
  • <copyright>:詳細說明版權信息。
  • <generator>:說明產生這個Rss源的應用程序。

除了上面的這些標籤,還可以有一個或多個<item>標籤。Item標籤代表着你想要分享的實際條目。比如,文章、博客入口。每個<item>標記進一步包含下面這些子結點。

  • <title>:代表着這個條目的標題。比如:文章標題。
  • <author>:代表着這個條目的作者。比如:文章作者。
  • <link>:代表這個條目的URL。比如:文章的URL。
  • <description>:包含着這個條目的描述信息。比如:文章的摘要。
  • <pubDate>:這個標籤包含着這個條目的發佈日期。典型的日期格式是:Sun 28 Dec 2003 12:00:00 AM GMT.

採用的方法

OK,我們已經對Rss的格式做了瞭解,但是如何使用.Net生成Rss源?.Net有許多XML相關的類。我們將從這些類中使用XML Text Writer來生成 Rss源。但是我們應該開發出一個通用的解決方案以便在任何的web站點中都可以使用。這就意味着我們的代碼必須獨立於特定的數據庫領域或者表。爲了達到這個目的,我們將要在VS.NET中創建一個類庫。我們Rss的<item>標記的數據源將採用一個Dataset,這個Dataset通常填充自數據庫表。這個類將有下面的屬性和方法。

  • 屬性

  • Outputstream:一個源所投遞到的stream對象。
  • RssTitle:代表<channel>標籤下的<title>的特定值。
  • PublisherUrl:代表<channel>標籤下的<link>標籤。
  • Description:代表<channel>標籤下的<description>值。
  • Copyright:代表<channel>標籤下的<copyright>值。
  • Generator:代表<channel>標籤下的<generator>值。
  • ItemSource:指定一個包含着item行的Dataset對象。
  • ItemTitleField:數據列,代表<item>標籤下的<title>標籤
  • ItemUrlField:數據列,代表<item>標籤下的<link>標籤。
  • ItemDescriptionField:數據列,代表<item>標籤下的<description>標籤。
  • ItemPublicationDateFiled:數據列,代表<item>標籤下的<pubDate>標籤。
  • ItemAuthor:數據列,代表<item>標籤下的<author>標籤。

方法

  • PublishRss:這個靜態方法將Rss標記寫入到outputstream(輸出流)中。

下面列出的是上面這些屬性和方法的完整程序清單。爲了簡單和快速地作個示範,我使用了公用字段,而沒有使用屬性。在實際的應用程序中,應該使用屬性。

using System;
using System.IO;
using System.Data;
using System.Xml;
using System.Collections.Generic;
using System.Text;

public class Rss {
    public Stream OutputStream;
    public string RssTitle;
    public string PublisherUrl;
    public string Description;
    public string Copyright;
    public string Generator;
    public DataSet ItemSource;
    public string ItemTitleField;
    public string ItemUrlField;
    public string ItemDescriptionField;
    public string ItemPublicationDateField;
    public string ItemAuthor;

    public static void PublishRss(Rss r){
       XmlTextWriter writer = new XmlTextWriter(r.OutputStream, Encoding.UTF8);
writer.WriteStartDocument();
       writer.WriteStartElement("rss");
       writer.WriteAttributeString("version", "2.0");
       writer.WriteStartElement("channel");
       writer.WriteElementString("title", r.RssTitle);
       writer.WriteElementString("link", r.PublisherUrl);
       writer.WriteElementString("description", r.Description);
       writer.WriteElementString("copyright", r.Copyright);
       writer.WriteElementString("generator", r.Generator);

       foreach (DataRow row in r.ItemSource.Tables[0].Rows) {
           writer.WriteStartElement("item");
           writer.WriteElementString("author", row[r.ItemAuthor].ToString());
           writer.WriteElementString("title", row[r.ItemTitleField].ToString());
           writer.WriteElementString("link", row[r.ItemUrlField].ToString());
           writer.WriteElementString("description", row[r.ItemDescriptionField].ToString());
           writer.WriteElementString("pubDate", Convert.ToDateTime(row[r.ItemPublicationDateField]).ToString("dd MMM yyyy hh:mm:00 "));
           writer.WriteEndElement();
       }

       writer.WriteEndElement();
       writer.WriteEndElement();
       writer.Flush();
    }
}

NOTE:這裏pubDate的日期格式很重要,當你按上面的代碼對pubDate進行格式轉換的時候,假如數據庫中是 2007-9-14 9:58,那麼在英文操作系統下,會轉換成 “14 Sep 2007 9:58”,這個是沒有問題的。但在中文操作系統下,就變成了 “14 九月 2007 9:58”。導致的結果就是在IE7中點開rss源的時候,發現日期沒有顯示。如果你不進行數據格式轉換,簡單的使用一個 ToString(),結果仍是如此。這裏,我是寫了一個方法,對它進行了格式轉換:

// ... 省略 ...
writer.WriteElementString("pubDate", GetRssDate(row[r.ItemPublicationDateField]));
// ... 省略 ...

public static string GetRssDate(Object date) {
    DateTime rssDate = Convert.ToDateTime(date);
   string[] monthName = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };

    StringBuilder sb = new StringBuilder();
    sb.Append(rssDate.Day);
    sb.Append(" ");
    sb.Append(monthName[Convert.ToInt32(rssDate.Month) - 1]);
    sb.Append(" ");
    sb.Append(rssDate.Year);
    sb.Append(" ");
    sb.Append(rssDate.ToLongTimeString());

    return sb.ToString();
}

我看到ToString()有一個重載了的方法,接受一個IFormatProvider類型的參數,這個應該是進行格式轉換的標準方式,MSDN的範例有點長了,就沒有研究下去。如果哪位朋友對這裏有好的解決方法,可以在回覆在評論中,Thanks。

創建屬性就像上面顯示的那樣容易。PublishRss()方法是我們這裏關心的核心內容。我們創建了System.Xml.XmlTextWriter類的實例。這個類是撰寫XML文檔的快速方式。在這個例子中,我們傳遞進一個OutputStream對象,並確定編碼(UTF-8)。然後我們開始寫入這個文檔的不同部分。我們使用XmlTextWriter類的下面這些方法。

  • WriteStartDocument():這個方法寫入XML 1.0版本的聲明。也就是:
  • <?xml version="1.0" encoding="utf-8"?>。當不寫這個聲明的時候,在FireFox中雖然可以訂閱,但是看不到任何條目,也不能進行更新。IE7下正常。
  • WriteStartElement:這個方法寫入指定標籤的起始標記。
  • WriteAttributeString:這個方法爲當前打開的標籤寫入屬性。
  • WriteElementString:這個方法寫入一個起始標記和一個結束標記,以及起始和結束標記之間的文本。
  • WriteEndElement:這個方法寫入當前打開標記的結束標記。不需要在這裏指明結束標記的名字,因爲在每次嵌套的時候都會在內部(NOTE:屬於底層機制)設定。
  • Flush:這個方法將所有緩存的output清出到目的位置。

注意,你必須恰當地調用 WriteStartElement()和WriteEndElement()方法以生成格式良好的(well formed)XML 文檔。

創建Asp.Net Web窗體

現在我們已經創建好了一個通用類,我們可以在我們的Web窗體中使用它。假設我們將以Rss源形式發佈的數據存儲在一個表格(Article)中,這個表格的結構如下:

  • Title           - Varchar(255)
  • Description     - Varchar(1000)
  • Url             - Varchar(255)
  • Author          - Varchar(50)
  • Pubdate         - DateTime

以DataSet形式獲取Table內容

我們將在Asp.Net Web應用程序中創建一個Rss.aspx文件,在CodeBehind中創建一個 GetDataSet()方法。這個方法使用DataAdapter來填充一個Dataset。

public DataSet GetDataSet() {
    SqlConnection conn = new SqlConnection("你的連接字符串");
    string sql = "Select * From Article Order By ArticleId Desc";
    SqlDataAdapter da = new SqlDataAdapter(sql,conn);
    DataSet ds = new DataSet();

    da.Fill(ds, "Article");
    return ds;
}

接着,我們創建一個Rss類的實例,設置它的各個屬性,然後調用GetDataSet()方法獲取DataSet對象。

protected void Page_Load(object sender, EventArgs e){
    DataSet ds = GetDataSet();
    Rss rss = new Rss();
    rss.OutputStream = Response.OutputStream;
    rss.RssTitle = "DotNetBips.com Latest Articles";
    rss.PublisherUrl = Request.Url.Host;
    rss.Description = "DotNetBips.com - Applying .NET";
    rss.Copyright = "Copyright (C) DotNetBips.com.";
    rss.Generator = "DotNetBips.com RSS Generator";
    rss.ItemSource = ds;
    rss.ItemTitleField = "Title";
    rss.ItemDescriptionField = "Description";
    rss.ItemPublicationDateField = "Pubdate";
    rss.ItemUrlField = "Url";
    rss.ItemAuthor = "Author";
    Response.ContentEncoding = System.Text.Encoding.UTF8;
    Response.ContentType = "text/xml";
    Rss.PublishRss(rss);
    Response.End();
}

當我們獲得DataSet後,將ItemSource屬性設置爲這個DataSet。另外,我們再設置Response對象的ContentEncoding和ContentType屬性。然後,調用PublishRss()方法,將這個Rss類的實例傳遞進去。

OK,現在我們在IE中瀏覽Rss.aspx頁面,應該可以看到如下圖所示的畫面:

NOTE:注意,此時 創建Rss源的類名和 Rss.aspx CodeBehind中的Page類名將會一樣,都是Rss,所以需要手動修改Rss.aspx.cs 中的Page類名,比如,改爲_Rss,則代碼如下:
    public partial class _Rss : System.Web.UI.Page
   同時,修改HTML頁面的 inherints :
   Inherits="_Rss"

消費Rss源

創建了Rss源以後,其他的站點可以消費這個Rss源。我會以創建一個顯示 www.asp.net 最新文章的Web窗體來作爲範例。

NOTE:我想應該是因爲對於發佈Rss源的站點來說,使用源的站點是消費者Consumer,所以英文技術文章中使用源通常都用Consume這個詞,而不用Use。

爲了能通過一個URL來讀取XML的數據,我們當然可以使用 WebRequest 和 WebResponse 對象(參考我的文章 Using WebRequest and WebResponse)。然而,有一個更簡單的方法 – DataSet。

DataSet類有一個叫做ReadXml()的方法,可以從硬盤的文件或者URL中讀取XML數據。這個方法讀取數據並自動爲我們生成所需的DataTable。

DataSet ds = new DataSet();
ds.ReadXml("http://127.0.1.1/rss.aspx");

這裏,我們創建了一個DataSet的實例,並且通過傳遞URL參數來調用ReadXml()方法。可以根據需要來改變傳進去的URL參數。

NOTE:我房子暫時沒有上網,所以就使用前面所創建的本地Rss源作爲演示。

ReadXml()方法生成的表格

如果你期望ReadXml()方法會生成一個DataTable,其中包含着鏈接的列表,你會驚奇地發現實際上會生成三個DataTable。在 RSS 的格式 這一小節的XML標記中,我們看到標記是嵌套的,DataSet會在讀取數據的時候自動創建相關表。它也會爲每個DataTable創建ID字段以便他們可以相互鏈接。

在這個例子中,你會得到下面構架的 DataTable:

RSS

  • Rss_Id
  • Version

Channel

  • Title
  • Link
  • Description
  • Language
  • Generator
  • Channel_Id
  • Rss_Id

Item

  • Creator
  • Title
  • Link
  • PubDate
  • Guid
  • Description
  • Channel_Id

注意一些字段,比如Creator和 Guid 並沒有在Rss標記中出現。另外注意DataSet是如何添加Rss_Id和Channel_Id這樣的字段來關聯DataTable的。

現在我們已經知道了表的結構,讓我們編寫一些代碼來在GridView中顯示這些數據。

在GridView中顯示數據

從Rss源中獲得的詳細信息來看,第三張表是最重要的,因爲它包含了實際的鏈接數據。這裏我們將我們的GridView與第三個DataTable進行綁定。

GridView1.DataSource = ds.Tables[2].DefaultView;
GridView1.DataBind();

一旦你在PageLoad事件中調用這段代碼,可以看到類似下面這樣的屏幕截圖:

加入瀏覽器支持

IE7 和 FireFox 都提供了對Rss的支持,爲了使瀏覽器提供Rss支持,你必須先告訴它們你的站點創建了Rss源。只需要在<head></head>標籤中加入如下代碼即可:

<link rel="alternate" type="application/rss+xml" title="Your Web Site’s RSS Feed Title " href="http://www.yourdomain.net/rss.aspx" />

這時再打開加入上面<link>的頁面,會發現IE7的 RSS圖標由灰色變成了明亮的桔紅色。

總結

在這篇文章中,我們瞭解了什麼是RSS,以及如何爲你的站點生成RSS源。我們使用XmlTextWriter類來創建Rss標記。我們創建了一個通用類,以便它可以在任何Web應用程序中使用。

隨後,我們瞭解瞭如何使用DataSet來消費Rss源。Rss源是一個嵌套的XML標記,DataSet自動創建彼此相關的DataTable。第三張表(ITem)包含了Rss源的核心數據。

希望這篇文章能給你帶來幫助

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章