خواندن فید های Rss2 و نمایش آن در Asp.net

RSS چیست ؟
RSS به قولی سرنام REALLY SIMPLE SYNDICATION و به قول کمی حرفه‌ای‌ترها سرنام RDF SITE SUMMARY است. ولی RSS سرنام هر چه باشد، پدیده‌ای است که امکان جمع‌آوری اطلاعات و اخبار را از سایت‌های مختلف فراهم می‌کند بدون این که مجبور باشید از این سایت به آن سایت سر بزنید. ویژگی RSS هم مثل بقیه تکنولوژی‌های خوب، در سادگی آن است :یک فرمت سریع و استاندارد، شبیه همان بولتن‌های خبری است منتها به شکل الکترونیک. امروزه اکثر سایت‌های وب مهم به این بولتن‌ها مجهز هستند، از وبلاگ‌های شخصی گرفته تا سایت‌های خبرگزاری‌های بزرگ دنیا. برای گرفتن این بولتن‌ها کافی است نرم‌افزار مناسب این کار را در اختیار داشته باشید و بولتن مورد نظر را مشترک شوید. شاید فکر کنید خواندن خبرها که کاری ندارد، به صفحه اصلی سایت می‌رویم و خبرها را می‌خوانیم. اما حالتی را در نظر بگیرید که بخواهید 50 سایت مختلف را ببینید و تازه معلوم نیست این سایت‌ها اصلاً خبر جدیدی داشته باشند یا نه. با RSS نیازی نیست به 50 تا سایت سر بزنید. کامپیوتر شما به طور خودکار و با زمان‌بندی مشخص با این سایت‌ها تماس می‌گیرد و جدیدترین خبرها و اطلاعات را دانلود می‌کند. بنابراین، فقط از یک پنجره می‌توانید تمام اتفاقات روز را مشاهده کنید. بدین ترتیب هم در وقت‌تان صرفه‌جویی کرده‌اید، و هم در این همه اطلاعات اضافی که در وب وجود دارد گرفتار نشده‌اید.

در اینجا قصد داریم با استفاده از یک متد ساده اطلاعات  RSS یک سایت را خوانده و در یم صفحه Asp.net نمایش دهیم . کد های به زبان سی شارپ میباشد .

برای خواندن اطلاعات از RSS ابتدا یک کلاس ساخته و سپس یک متد و چند مشخصه به صورت زیر برای کلاس تعریف کرده .

01.private string feedname;
 02.private string rssurl;
 03.private int countitem;
 04.public string Rssurl
 05.{
06.get { return rssurl; }
 07.set { rssurl = value; }
 08.}
 09.public string Feedname
 10.{
 11.get { return feedname; }
 12.set { feedname = value; }
 13.}
 14.public int Countitem
 15.{
 16.get { return countitem; }
 17.set { countitem = value; }
 18.}
 
تعریف مشخصه های کلاس :
Rssurl = آدرس Rss2 سایت مورد نظر را دریافت میکند .
Feedname = نام سایت مورد نظر را دریافت میکند .
Countitem = تعداد مطالبی را که باید در صفحه نمایش داده شود مشخص میکند  .

سپس کلاس ما حاوی یک متد است برای انجام عملیات خواندن فید . نام کلاس را ProcessRSS قرار میدهیم و اطلاعات را در قالب یک رشته برگشت میدهیم .
01.public string ProcessRSS()
 02.{
 03.if (string.IsNullOrEmpty(Rssurl))
 04.{
 05.throw new NotAddressRssException();
 06.}
 07.WebRequest request = WebRequest.Create(Rssurl);
 08.WebResponse response = request.GetResponse();
 09.StringBuilder sb = new StringBuilder(string.Empty);
 10.Stream rssStream = response.GetResponseStream();
 11.XmlDocument rssDoc = new XmlDocument();
 12.rssDoc.Load(rssStream);
 13.XmlNodeList rssItems = rssDoc.SelectNodes("rss/channel/item");
 14.string title = "";
 15.string link = "";
 16.int upperlimit = rssItems.Count;
 17.if (upperlimit > Countitem)
 18.upperlimit = Countitem;
 19.if (upperlimit > 0)
 20.{
21.sb.Append("
" + Feedname + "
");
 22.for (int i = 0; i < upperlimit; i++)
 23.{
 24.XmlNode rssDetail;
 25.rssDetail = rssItems.Item(i).SelectSingleNode("title");
 26.if (rssDetail != null)
 27.{
 28.title = rssDetail.InnerText;
 29.}
 30.else
 31.{
 32.title = "";
 33.}
 34.rssDetail = rssItems.Item(i).SelectSingleNode("link");
 35.if (rssDetail != null)
 36.{
 37.link = rssDetail.InnerText;
 38.}
 39.else
 40.{
 41.link = "";
 42.}
43.sb.Append("
    %22%20+%20link%20+%20%22" target="_blank">" + title + "
");
44.}
 45.sb.Append("");
 46.}
 47.return sb.ToString().Trim();
 48.}
 49.}
 

نحوه کار متد به صورت زیر است :
در ابتدا بررسی میشود که آیا کاربر آدرس فید را وارد کرده است یا خیر ، اگر کاربر آدرس را وارد نکرده باشد یک Exception پرتاب خواهد شد . (این Exception به صورت کلاس تعریف شده است که در آخر مقاله بررسی میشود . )
در مرحله بعدی با استفاده از شئ WebRequest  درخواست برای گرفتن اطلاعات به آدرس فید ارسال میشود . با شئ WebResponse  اطلاعات دریافت میشود .
در مرحله بعدی یک  Stream  ساخته شده و اطلاعات به صورت Stream  دریافت میشودند .
ساختار فایل  RSS به صورت یک فایل XML میباشد و ما باید با این اطلاعات به وسیله کتابخانه های کار با XML کار کنیم . به این منظور یک شئ XmlDocument  برای کار با اطلاعات که در قالب XML میباشد ایجاد میشود .
سپس اطلاعات داخل شئ XmlDocument   قرار میگیرند .
یک شئ XmlNodeList  برای کار با اعضای فایل XML ساخته میشود و نام آن را rssItems  قرار میدهیم .
اطلاعات هر مطلب در RSS داخل تگ item قرار میگیرد که خود تگ item داخل تگ channel قرار دارد و تگ channel داخل تگ rss . پس برای دسترسی به تگ item  به این  صورت آدرس دهی میکنیم. rss/channel/item  به این صورت اطلاعات item داخل rssItems   قرار میگیرد .
لازم به ذکر است که اطلاعات مطلب RSS داخل تگ های مختلف در item قرار میگیرد . مثلاً داخل تگ title عنوان مطلب قرار میگیرد و داخل تگ link لینک مطلب در سایت اصلی قرار دارد .
برای مشاهده تگ های کامل item به این صفحه مراجعه کنید .
در مرحله بعد تعداد مطالبی که باید استخراج شود با توجه به تنظیم کاربر صورت میگیرد . و سپس داخب متغیر upperlimit  قرار میگیرد .
سپس اطلاعات به حلقه For دریافت شده و نمایش داده میشود .
همان طور که گفته شد ما در اینجا فقط از تگ های title و link استفاده کردیم . شما با در نظر گرفتن نیاز خود میتوانید از تگ های بیشتری استفاده کنید .
در مرحله بعد اطلاعات به دست آمده از هر item به sb که یک StringBuilder میباشد اضافه میشود .
سپس کل اطلاعات sb برگشت داده میشود .

کلاس NotAddressRssException که از Exception مشتق شده است . در صورتی که آدرس RSS خالی باشد پرتاب میشود .
 
 01.public class NotAddressRssException : Exception
 02.{
 03.private DateTime dateTimeError;
 04.public DateTime DateTimeError
 05.{
 06.get { return dateTimeError; }
 07.set { dateTimeError = value; }
 08.}
 09.public NotAddressRssException()
 10.: base(&quot;آدرس فید را وارد کنید&quot;)
 11.{
 12.dateTimeError = DateTime.Now;
 13.}
 14.}
 
  این کلاس حاوی یک مشخصه است که تاریخ و ساعت رخ دادن خطا را گزارش میدهد .

برای استفاده از این کلاس به صورت زیر عمل میکنیم  .
ابتدا در صفحه یک کنترل Literal قرار میدهیم . سپس کد زیر را در رویداد Load صفحه مینویسم .
 
01.protected void Page_Load(object sender, EventArgs e)
 02.{
 03.try
 04.{
05.RssReader feed = new RssReader();
 06.feed.Feedname = &quot;.: Mehrdad Ghasemi Official WebSite :.&quot;;
 07.feed.Rssurl = &quot;http://www.mehrdadg.ir/rss2.aspx&quot;;
 08.feed.Countitem = 10;
 09.this.Literal1.Text = feed.ProcessRSS();
10.}
 11.catch (NotAddressRssException ex)
 12.{
 13.this.Literal1.Text = ex.Message.ToString()+ &quot;
 14.&quot;+ ex.DateTimeError.ToString();
 15.}
 16.catch (Exception ex)
 17.{
 18.this.Literal1.Text = ex.Message.ToString();
 19.}
20.}

همان طورکه میبینید ، ابتدا یک شئ از کلاس RssReader  ایجاد میکنیم . سپس مشخصه های این کلاس را مشخص میکنیم . سپس متد ProcessRSS را فراخانی میکنیم و نتیجه را مشاهده میکنیم .

روش دوم:

بصورت یک فایل کلاس درست شده که براحتی در هر پروژه قابل استفاده باشد

فایل کلاس

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net;
using System.Text;
using System.Xml;
using System.IO;

namespace Simpa.Classes
{
    public class Simpa_RSS
    {



        private string str_RSS_Feed_Name;

        private string str_RSS_Feed_URL;

        private int int_RSS_Feed_Count_Item;

        public string wuc_str_RSS_Feed_URL
        {
            get { return str_RSS_Feed_URL; }

            set { str_RSS_Feed_URL = value; }

        }

        public string wuc_str_RSS_Feed_Name
        {

            get { return str_RSS_Feed_Name; }

            set { str_RSS_Feed_Name = value; }

        }

        public int wuc_int_RSS_Feed_Count_Item
        {

            get { return int_RSS_Feed_Count_Item; }

            set { int_RSS_Feed_Count_Item = value; }

        }

        string Result_Rss_Pattern;
        public string wuc_Result_Rss_Pattern
        {
            set { Result_Rss_Pattern = value; }
        }



        private string ProcessRSS()
        {

            if (string.IsNullOrEmpty(wuc_str_RSS_Feed_URL))
            {

                throw new NotAddressRssException();

            }

            WebRequest request = WebRequest.Create(wuc_str_RSS_Feed_URL);

            WebResponse response = request.GetResponse();

            StringBuilder sb = new StringBuilder(string.Empty);

            Stream rssStream = response.GetResponseStream();

            XmlDocument rssDoc = new XmlDocument();

            rssDoc.Load(rssStream);

            XmlNodeList rssItems = rssDoc.SelectNodes("rss/channel/item");

            string str_Rss_Node_Title = "";

            string str_Rss_Node_Link = "";

            string str_Rss_Node_Description = "";

            string str_Temp = "";




            int upperlimit = rssItems.Count;

            if (upperlimit > int_RSS_Feed_Count_Item)

                upperlimit = int_RSS_Feed_Count_Item;

            if (upperlimit > 0)
            {
                sb.Append(" " + str_RSS_Feed_Name + "");

                for (int i = 0; i < upperlimit; i++)
                {

                    XmlNode rssDetail;

                    rssDetail = rssItems.Item(i).SelectSingleNode("title");

                    if (rssDetail != null)
                    {

                        str_Rss_Node_Title = rssDetail.InnerText;

                    }

                    else
                    {

                        str_Rss_Node_Title = "";

                    }

                    rssDetail = rssItems.Item(i).SelectSingleNode("link");

                    if (rssDetail != null)
                    {

                        str_Rss_Node_Link = rssDetail.InnerText;

                    }

                    else
                    {

                        str_Rss_Node_Link = "";

                    }


                    rssDetail = rssItems.Item(i).SelectSingleNode("description");

                    if (rssDetail != null)
                    {

                        str_Rss_Node_Description = rssDetail.InnerText;

                    }

                    else
                    {

                        str_Rss_Node_Description = "";

                    }



                    //   sb.Append("<br><a href=\"" + link + "\" alt=\"" + title + "\" title=\"" + title + "\" target=blank>" + title + "</a>");
                    ///   sb.Append(Result_Part_1 + link + Result_Part_2 + title + Result_Part_3);

                    str_Temp = Result_Rss_Pattern;
                    str_Temp = str_Temp.Replace("#title#", str_Rss_Node_Title);
                    str_Temp = str_Temp.Replace("#link#", str_Rss_Node_Link);
                    str_Temp = str_Temp.Replace("#description#", str_Rss_Node_Description);
                    sb.Append(str_Temp);


                }

                sb.Append("");

            }

            return sb.ToString().Trim();

        }



        /// <summary>
        /// تابع اصلی فراخوانی RSS
        /// با تشکر و برگرفته شده از  http://irancsharp.net/Post-80.aspx
        /// </summary>
        /// <param name="str_Feed_Name">نام و مشخصاتی که در ابتدای  لیست نمایش داده میشود</param>
        /// <param name="str_Feed_URL">آدرس URL RSS</param>
        /// <param name="str_Feed_Count">تعداد  آیتمهای فراخوانی شده</param>
        /// <param name="str_Feed_Pattern">قالب خاص جهت نمایش و قالب بندی خروجی</param>
        /// Pattern = <br><a href='#link#'  alt='#title#'  title='#title#' >#title#</a> <br>#description#<hr>
        /// <returns>محتویات بصورت RSS بصورت یک رشته جهت درج در  یک کنترل نمایشی مانند لیبل یا لیترال</returns>
        public string Simpa_RSS_Reader(string str_Feed_Name, string str_Feed_URL, int str_Feed_Count, String str_Feed_Pattern)
        {
            string str_Result = string.Empty;
            try
            {

                Simpa_RSS obj_Simpa_RSS = new Simpa_RSS();

                obj_Simpa_RSS.wuc_str_RSS_Feed_Name = str_Feed_Name;//  

                obj_Simpa_RSS.wuc_str_RSS_Feed_URL = str_Feed_URL; //////           // "http://www.tabnak.ir/fa/rss/4";

                obj_Simpa_RSS.wuc_int_RSS_Feed_Count_Item = str_Feed_Count;

                obj_Simpa_RSS.wuc_Result_Rss_Pattern = str_Feed_Pattern;

                str_Result = obj_Simpa_RSS.ProcessRSS();

            }

            catch (NotAddressRssException ex)
            {

                str_Result = ex.Message.ToString() + "&quot;" + ex.DateTimeError.ToString();

            }

            catch (Exception ex)
            {

                str_Result = ex.Message.ToString();

            }
            return str_Result;
        }




    }



    public class NotAddressRssException : Exception
    {

        private DateTime dateTimeError;

        public DateTime DateTimeError
        {

            get { return dateTimeError; }

            set { dateTimeError = value; }

        }

        public NotAddressRssException()

            : base("&quot;آدرس فید را وارد کنید&quot;")
        {

            dateTimeError = DateTime.Now;

        }
    }

}

صفحه aspx

using Simpa.Classes;
   ...
              Literal1.Text = "Start at " + DateTime.UtcNow.AddHours(3.5).ToString("HH:mm:ss") + "<br>";
            Simpa_RSS obj_Simpa_RSS = new Simpa_RSS();
        //    Literal1.Text += obj_Simpa_RSS.Simpa_RSS_Reader(txt_Feed_Name.Text, txt_Feed_URL.Text, int.Parse(txt_Feed_Count.Text), txt_Pattern.Text);
   Literal1.Text += obj_Simpa_RSS.Simpa_RSS_Reader("My RSS Feed", "http://www.tabnak.ir/fa/rss/4", 10, "&lt;br&gt;&lt;a href='#link#'  alt='#title#'  title='#title#' &gt;#title#&lt;/a&gt; &lt;br&gt;#description#&lt;hr&gt;");
            Literal1.Text += "<br>End at " + DateTime.UtcNow.AddHours(3.5).ToString("HH:mm:ss");