Tvorba RSS feed XML v C#

Jan Holan       24. 6. 2011       XML, ASP.NET/IIS       6225 zobrazení

Dnes ukáži jednoduchou třídu RssFeedWriter, která slouží pro tvorbu RSS feed XML dokumentu. Třídu využijeme jako součást ASP.NET handleru NewsFeed, který bude výsledek posílat do výstupu browseru.

using System;
using System.Web;
using System.Collections.Generic;
using System.IO;

public class NewsFeed : IHttpHandler
{
    private List<RssFeedItem> RssFeeds = new List<RssFeedItem>()
    {
        new RssFeedItem() { Title = "Pozvánka na WUG", Date = new DateTime(2011, 4, 25), Description = @"Jako spoluorganizátoři vývojářské části pražské pobočky WUG Vás zveme na přednášku Štěpána Bechynského o HTML 5 konané 27.4.2011 od 17:30 v budově Microsoft (bližší informace najdete <a href=""http://www.wug.cz/praha/akce/395-HTML5"" target=""_blank"">zde</a>) a na přednášku Michaela Juřka o využití TFS 2010 v malých týmech konané 31.5.2011 od 17:30 na stejném místě (bližší informace najdete <a href=""http://www.wug.cz/praha/akce/400-Team-Foundation-Server-2010-pro-male-tymy"">zde</a>)." },
        new RssFeedItem() { Title = "Silverlight 4.0 aplikace", Date = new DateTime(2011, 3, 3), Description = @"Úspěšně jsme nasadili intranetovou business aplikaci implementovanou v progresivní technologii <strong>Silverlight 4.0</strong>. Tím se nám podařilo zákazníkovi nabídnout maximální uživatelskou přívětivost v porovnání s klasickou webovou aplikací." },
        new RssFeedItem() { Title = "Facebook stránky", Date = new DateTime(2011, 2, 22), Description = @"Od tohoto okamžiku nás můžete sledovat i na facebooku na adrese:<br><a href=""http://www.facebook.com/home.php#!/pages/IMP-spol-s-r-o/201728966506988"" target=""_blank"">http://www.facebook.com/home.php#!/pages/IMP-spol-s-r-o/201728966506988</a>" }
    };
    
    public class RssFeedItem
    {
        public string Title { get; set; }
        public DateTime Date { get; set; }
        public string Link { get; set; }
        public string Description { get; set; }
    }

    /// <summary>
    /// Enables processing of HTTP Web requests by a custom HttpHandler that implements the System.Web.IHttpHandler interface.
    /// </summary>
    /// <param name="context">An System.Web.HttpContext object</param>
    public void ProcessRequest(HttpContext context)
    {
        context.Response.Cache.SetExpires(DateTime.MinValue);
        context.Response.ContentType = "text/xml";

        var feed = new RssFeedWriter()
        {
            Title = "IMP spol. s r.o.",
            Description = "Novinky IMP spol. s r.o.",
            Link = "http://www.imp.cz/newsfeed",
            Language = new System.Globalization.CultureInfo("cs-CZ"),
            Items = RssFeeds
        };

        feed.WriteTo(context.Response.OutputStream);
    }

    /// <summary>
    /// Gets a value indicating whether another request can use the System.Web.IHttpHandler instance.
    /// </summary>
    public bool IsReusable
    {
        get { return true; }
    }

    public class RssFeedWriter
    {
        #region member varible and default property initialization
        private List<RssFeedItem> m_Items = new List<RssFeedItem>();

        public string Title { get; set; }
        public string Link { get; set; }
        public string Description { get; set; }
        public System.Globalization.CultureInfo Language { get; set; }
        #endregion

        #region property getters/setters
        public List<RssFeedItem> Items
        {
            get { return m_Items; }
            set { m_Items = value; }
        }
        #endregion

        #region action methods
        public void WriteTo(Stream stream)
        {
            string s = GenerateRss();
            using (StreamWriter sw = new StreamWriter(stream, System.Text.Encoding.UTF8))
            {
                sw.Write(s);
            }
        }

        public override string ToString()
        {
            return GenerateRss();
        }
        #endregion

        #region private member functions
        private string GenerateRss()
        {
            var sb = new System.Text.StringBuilder();
            using (var sw = new StringWriterWithEncoding(sb, System.Text.Encoding.UTF8))
            {
                using (var xtw = new System.Xml.XmlTextWriter(sw))
                {
                    //Write Headers
                    xtw.WriteStartDocument();

                    xtw.WriteStartElement("rss");
                    xtw.WriteAttributeString("version", "2.0");
                    xtw.WriteStartElement("channel");
                    xtw.WriteElementString("title", Title);
                    if (!string.IsNullOrEmpty(Link))
                    {
                        xtw.WriteElementString("link", Link);
                    }
                    xtw.WriteElementString("description", Description);
                    xtw.WriteElementString("language", Language.Name);

                    //Write Items
                    foreach (var item in Items)
                    {
                        xtw.WriteStartElement("item");
                        xtw.WriteElementString("title", item.Title);
                        xtw.WriteElementString("description", item.Description);
                        if (!string.IsNullOrEmpty(item.Link))
                        {
                            xtw.WriteElementString("link", item.Link);
                        }

                        xtw.WriteElementString("pubDate", item.Date.ToString("ddd, dd MMM yyyy 00:00:00 +0100", System.Globalization.CultureInfo.InvariantCulture));                        

                        xtw.WriteEndElement();
                    }

                    xtw.WriteEndDocument();
                }
            }
            return sb.ToString();
        }
        #endregion
    }

    public class StringWriterWithEncoding : StringWriter
    {
        private System.Text.Encoding encoding;

        public StringWriterWithEncoding(System.Text.StringBuilder sb, System.Text.Encoding encoding) : base(sb)
        {
            this.encoding = encoding;
        }

        public override System.Text.Encoding Encoding
        {
            get { return encoding; }
        }
    }
}

Kód je docela jednoduchý, ale i tak se sluší zmínit pár poznámek k uvedenému řešení:

  • Jednotlivé položky RSS dokumentu jsou zde nastaveny do listu natvrdo. Třída RssFeedItem obsahuje Title, Date, Description a případně Link.
  • V metodě ProcessRequest handleru je nejprve na začátku nastavena expirace cache a ContentType pro RSS na "text/xml".
  • Pro tvorbu XML použijeme třídu XmlTextWriter, ta automaticky zajistí při zápisu hodnot i potřebné zaenkodování stringu pro XML. (Všimněte si, že v hodnotě Description se nachází HTML kód.)
  • Výsledek RSS je v UTF8. Při tvorbě potřebujeme zajistit, aby bylo třídou XmlTextWriter vytvořeno XML s : <?xml version="1.0" encoding="utf-8"?>. K tomu potřebujeme patřičný encoding nastavit třídě StringWriter. To ale nelze provést přímo, proto to provedeme pomoci třídy StringWriterWithEncoding – poděděný StringWriter, s override vlastností Encoding.
  • Posledním problémem při tvorbě RSS je položka pubDate. Jedná se o datum ve formátu např.:
    Tue, 22 Feb 2011 00:00:00 +0100, jeho formátování zde provádím takto:
    Date.ToString("ddd, dd MMM yyyy 00:00:00 +0100", System.Globalization.CultureInfo.InvariantCulture)
    V tomto případě nastavuji pouze datum bez času, pokud by se nastavoval i čas, tak pozor na správné uvedení časové zóny. InvariantCulture je zde proto, aby texty zkratek dne  v týdnu (ddd) a měsíce (MMM) byly anglické.

 

hodnocení článku

0       Hodnotit mohou jen registrované uživatelé.

 

Nový příspěvek

 

                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback