RssFeed Retrieve
From ICO wiki
using System;
using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.IO;
using System.Collections; using System.Xml;
namespace Scream.RSS {
public class RssManager { public void GetRssItemList(string url) { HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); Stream responseStream = response.GetResponseStream();
Encoding BrowserEncoding = Encoding.ASCII;
if (request.HaveResponse) { // Next is redirection if ((response.StatusCode == HttpStatusCode.Found) || (response.StatusCode == HttpStatusCode.Redirect) || (response.StatusCode == HttpStatusCode.Moved) || (response.StatusCode == HttpStatusCode.MovedPermanently)) { // Get new location and call recursively WebHeaderCollection responseHeaders = response.Headers; request = (HttpWebRequest)WebRequest.Create(responseHeaders["Location"]);
HttpWebResponse redirectedResponse = (HttpWebResponse)request.GetResponse();
responseStream = redirectedResponse.GetResponseStream(); } }
StringBuilder stringBuilder = new StringBuilder(); byte[] buffer = new byte[8192]; string tempString = null; int count = 0; do { // fill the buffer with data count = responseStream.Read(buffer, 0, buffer.Length); // make sure we read some data if (count != 0) { tempString = Encoding.UTF8.GetString(Encoding.Convert(BrowserEncoding, Encoding.UTF8, buffer, 0, count)); stringBuilder.Append(tempString); } } while (count > 0); // any more data to read?
string html = stringBuilder.ToString();
} }
#region Event datatype/delegate /// <summary> /// Holds details about any errors that occured /// during the loading or parsing of the RSS feed. /// </summary> public class RssReaderErrorEventArgs : EventArgs { /// <summary> /// The details of the error. /// </summary> public string Message { get { return this.message; } set { this.message = value; } }
private string message; }
/// <summary> /// Represents the method that will handle the RssReader error event. /// </summary> public delegate void RssReaderErrorEventHandler(object sender, RssReaderErrorEventArgs e); #endregion
#region RssReader class
/// <summary>
/// The RssReader class provides a number of static methods for easy
/// 1 or 2 step retrieval of RSS feeds. RSS feeds can be downloaded from any
/// URL, and are then parsed into an <see cref="RssFeed">RssFeed</see> data type,
/// which contains properties representing most aspects of an RSS Feed. A number
/// of events are available for the calling application to register at the various
/// stages of the feed request and parsing.
/// <example>
/// The following example retrieves the RSS news feed for the BBC news website,
/// and creates a HTML document from the feed's details. It saves the HTML document
/// to disk, and launches the default browser with the document. The number of items
/// displayed is limited to 5. If there is any error, a messagebox is displayed with
/// the details of the error.
///
/// RssFeed feed = RssReader.GetFeed("http://www.bbc.co.uk/syndication/feeds/news/ukfs_news/front_page/rss091.xml");
///
/// if ( feed.ErrorMessage == null || feed.ErrorMessage == "" )
/// {
/// string template = "<a href=\"%Link%>%Title%</a><br/>%Description%<br/><br/><ul>%Items%</ul>";
/// string itemTemplate = "<li><a href=\"%Link%>%Title%</a><br/>%Description%</li>";
/// string html = RssReader.CreateHtml(feed,template,itemTemplate,"",5);
///
/// StreamWriter streamWriter = File.CreateText("c:\\rss.html");
/// streamWriter.Write(html);
/// streamWriter.Close();
///
/// System.Diagnostics.Process.Start("c:\\rss.html");
/// }
/// else
/// {
/// MessageBox.Show("Error getting feed:\r\n" +feed.ErrorMessage,"Rss Demo App",MessageBoxButtons.OK,MessageBoxIcon.Exclamation);
/// }
///
/// </example>
/// </summary>
public class RssReader {
// Events: XML document loaded, rss element found,
// channel node found, item parsed, error
/// <summary> /// This event is fired when the feed has finished loading from the URL /// provided, into the XML parser. /// </summary> public event EventHandler FeedLoaded;
/// <summary> /// This event is fired when the root node (typically 'rss') has /// been found in the feed. /// </summary> public event EventHandler RssNodeFound;
/// <summary> /// This event is fired when the channel/child node of the rss node /// (typically 'channel') has been found in the feed. /// </summary> public event EventHandler ChannelNodeFound;
/// <summary> /// This event is fired when an item is added to the <see cref="RssFeed">RssFeed</see>'s /// collection of items. /// </summary> public event EventHandler ItemAdded;
/// <summary> /// This event is fired when an error occurs in the loading or parsing /// of the feed. The same error message is also available in the ErrorMessage /// property of the <see cref="RssFeed">RssFeed</see> object that is returned /// by the <see cref="Retrieve">Retrieve</see> method. /// </summary> public event RssReaderErrorEventHandler Error;
/// <summary> /// The node name for the channel element /// in the RSS feed. This will rarely ever to be /// changed. Default is 'channel'. /// </summary> public string RootNodeName { get { return this.rootNodeName; } set { this.rootNodeName = value; } }
/// <summary> /// The node name for the root rss element /// in the RSS feed. This is altered automatically to 'rdf:RDF' /// when RdfMode is set to true. Default is 'rss'. /// </summary> public string ChannelNodeName { get { return this.channelNodeName; } set { this.channelNodeName = value; } }
/// <summary> /// If this is set to true, then the XML document /// is parsed slightly different, to cater sites with RDF feeds (such as /// slashdot.org and register.com). The whole RDF format is not supported, /// but those items in RSS which have a corresponding RDF property, such /// as description,title for the channel, and title,description for each /// item, are matched. /// </summary> public bool RdfMode { get { return this.rdfMode; } set { if (value) { this.rootNodeName = "rdf:RDF"; } else { this.rootNodeName = "rss"; } this.rdfMode = value; } }
/// <summary> /// Member for the public property. /// </summary> private string rootNodeName = "rss";
/// <summary> /// Member for the public property. /// </summary> private string channelNodeName = "channel";
/// <summary> /// Member for the public property. /// </summary> private bool rdfMode = false;
/// <summary> /// Retrieves a <see cref="RssFeed">RssFeed</see> object using /// the url provided as the source of the Feed. /// </summary> /// <param name="Url">The url to retrieve the RSS feed from, this can /// be in the format of http:// and also file://.. (ftp?)</param> /// <param name="RdfFormat">If this is set to true, then the XML document /// is parsed slightly different, to cater sites with RDF feeds (such as /// slashdot.org and register.com). The whole RDF format is not supported, /// but those items in RSS which have a corresponding RDF property, such /// as description,title for the channel, and title,description for each /// item, are matched.</param> /// <returns>A <see cref="RssFeed">RssFeed</see> object from the /// RSS feed's details.</returns> public static RssFeed GetFeed(string Url, bool RdfFormat) { RssReader rssReader = new RssReader(); rssReader.RdfMode = RdfFormat; return rssReader.Retrieve(Url); }
/// <summary> /// Retrieves a <see cref="RssFeed">RssFeed</see> object using /// the url provided as the source of the Feed. /// </summary> /// <param name="Url">The url to retrieve the RSS feed from, this can /// be in the format of http:// and also file://.. (ftp?)</param> /// <returns>A <see cref="RssFeed">RssFeed</see> object from the /// RSS feed's details.</returns> public static RssFeed GetFeed(string Url) { RssReader rssReader = new RssReader(); return rssReader.Retrieve(Url); }
/// <summary> /// A simplified method of creating a HTML (or any document) from an /// RSS Feed. See <see cref="RssHtmlMaker">RssHtmlMaker</see> /// </summary> /// <param name="Feed">The <see cref="RssFeed">RssFeed</see> object to /// get the tokens' data from.</param> /// <param name="Template">The overall HTML template (or any other format) /// to replace the tokens in.</param> /// <param name="ItemPrefix">A string template that is prepended to the beginning /// of each RSS item.</param> /// <param name="ItemSuffix">A string template that is apppended to the end /// of each RSS item.</param> /// <returns>A string with the templates provided parsed of their tokens, with /// the data values in their place.</returns> public static string CreateHtml(RssFeed Feed, string Template, string ItemPrefix, string ItemSuffix) { return new RssHtmlMaker().GetHtmlContents(Feed, Template, ItemPrefix, ItemSuffix); }
/// <summary> /// A simplified method of creating a HTML (or any document) from an /// RSS Feed. See <see cref="RssHtmlMaker">RssHtmlMaker</see> /// </summary> /// <param name="Feed">The <see cref="RssFeed">RssFeed</see> object to /// get the tokens' data from.</param> /// <param name="Template">The overall HTML template (or any other format) /// to replace the tokens in.</param> /// <param name="ItemPrefix">A string template that is prepended to the beginning /// of each RSS item.</param> /// <param name="ItemSuffix">A string template that is apppended to the end /// of each RSS item.</param> /// <param name="MaxItems">The maximum number of RSS items to display.</param> /// <returns>A string with the templates provided parsed of their tokens, with /// the data values in their place.</returns> public static string CreateHtml(RssFeed Feed, string Template, string ItemPrefix, string ItemSuffix, int MaxItems) { RssHtmlMaker rssHtmlMaker = new RssHtmlMaker(); rssHtmlMaker.MaxItems = MaxItems; return rssHtmlMaker.GetHtmlContents(Feed, Template, ItemPrefix, ItemSuffix); }
/// <summary> /// Retrieves an RSS feed using the given Url, parses it and /// creates and new <see cref="RssFeed">RssFeed</see> object with the information. /// If an error occurs in the XML loading of the document, or parsing of /// the RSS feed, the error is trapped and stored inside the RssFeed's /// ErrorMessage property. /// </summary> /// <param name="Url">The url to retrieve the RSS feed from, this can /// be in the format of http:// and also file://.. (ftp?)</param> /// <returns>An <see cref="RssFeed">RssFeed</see> object with information /// retrieved from the feed.</returns> public RssFeed Retrieve(string Url) {
RssFeed rssFeed = new RssFeed(); rssFeed.Items = new RssItems();
XmlTextReader xmlTextReader = new XmlTextReader(Url); XmlValidatingReader xmlValidatingReader = new XmlValidatingReader(xmlTextReader); xmlValidatingReader.ValidationType = ValidationType.None;
XmlDocument xmlDoc = new XmlDocument();
try { xmlDoc.Load(xmlTextReader);
// Fire the load event if (this.FeedLoaded != null) { this.FeedLoaded(this, new EventArgs()); }
XmlNode rssXmlNode = null;
// Loop child nodes till we find the rss one for (int i = 0; i < xmlDoc.ChildNodes.Count; i++) { System.Diagnostics.Debug.Write("Child: " + xmlDoc.ChildNodes[i].Name); System.Diagnostics.Debug.WriteLine(" has " + xmlDoc.ChildNodes[i].ChildNodes.Count + " children");
if (xmlDoc.ChildNodes[i].Name == this.rootNodeName && xmlDoc.ChildNodes[i].ChildNodes.Count > 0) { rssXmlNode = xmlDoc.ChildNodes[i];
// Fire the found event if (this.RssNodeFound != null) { this.RssNodeFound(this, new EventArgs()); }
break; } }
if (rssXmlNode != null) { XmlNode channelXmlNode = null;
// Loop through the rss node till we find the channel for (int i = 0; i < rssXmlNode.ChildNodes.Count; i++) { System.Diagnostics.Debug.WriteLine("Rss child: " + rssXmlNode.ChildNodes[i].Name); if (rssXmlNode.ChildNodes[i].Name == this.channelNodeName && rssXmlNode.ChildNodes[i].ChildNodes.Count > 0) { channelXmlNode = rssXmlNode.ChildNodes[i];
// Fire the found event if (this.ChannelNodeFound != null) { this.ChannelNodeFound(this, new EventArgs()); }
break; } }
// Found the channel node if (channelXmlNode != null) { // Loop through its children, copying details to the // RssFeed struct, and parsing the items for (int i = 0; i < channelXmlNode.ChildNodes.Count; i++) { System.Diagnostics.Debug.WriteLine(channelXmlNode.ChildNodes[i].Name); switch (channelXmlNode.ChildNodes[i].Name) { case "title": { rssFeed.Title = channelXmlNode.ChildNodes[i].InnerText; break; } case "description": { rssFeed.Description = channelXmlNode.ChildNodes[i].InnerText; break; } case "language": { rssFeed.Language = channelXmlNode.ChildNodes[i].InnerText; break; } case "copyright": { rssFeed.Copyright = channelXmlNode.ChildNodes[i].InnerText; break; } case "webmaster": { rssFeed.Webmaster = channelXmlNode.ChildNodes[i].InnerText; break; } case "pubDate": { rssFeed.PubDate = channelXmlNode.ChildNodes[i].InnerText; break; } case "lastBuildDate": { rssFeed.LastBuildDate = channelXmlNode.ChildNodes[i].InnerText; break; } case "category": { rssFeed.Category = channelXmlNode.ChildNodes[i].InnerText; break; } case "generator": { rssFeed.Generator = channelXmlNode.ChildNodes[i].InnerText; break; } case "ttl": { rssFeed.Ttl = channelXmlNode.ChildNodes[i].InnerText; break; } case "rating": { rssFeed.Rating = channelXmlNode.ChildNodes[i].InnerText; break; } case "skipHours": { rssFeed.Skiphours = channelXmlNode.ChildNodes[i].InnerText; break; } case "skipDays": { rssFeed.Skipdays = channelXmlNode.ChildNodes[i].InnerText; break; } case "managingEditor": { rssFeed.ManagingEditor = channelXmlNode.ChildNodes[i].InnerText; break; } case "item": { rssFeed.Items.Add(this.getRssItem(channelXmlNode.ChildNodes[i]));
// Fire the found event if (this.ItemAdded != null) { this.ItemAdded(this, new EventArgs()); }
break; } }
}
// If rdf mode is set, then the channel node only contains // information about the channel, it doesn't hold the item // nodes. The item nodes are children of the root node in // an RDF document, so we use this instead. if (this.RdfMode) { for (int i = 0; i < rssXmlNode.ChildNodes.Count; i++) { switch (rssXmlNode.ChildNodes[i].Name) { case "item": { rssFeed.Items.Add(this.getRssItem(rssXmlNode.ChildNodes[i]));
// Fire the found event if (this.ItemAdded != null) { this.ItemAdded(this, new EventArgs()); }
break; } } } } } else { rssFeed.ErrorMessage = "Unable to find rss <seehannel> node";
// Fire the error event if (this.Error != null) { RssReaderErrorEventArgs args = new RssReaderErrorEventArgs(); args.Message = rssFeed.ErrorMessage; this.Error(this, args); } }
} else { rssFeed.ErrorMessage = "Unable to find root <rss> node";
// Fire the error event if (this.Error != null) { RssReaderErrorEventArgs args = new RssReaderErrorEventArgs(); args.Message = rssFeed.ErrorMessage; this.Error(this, args); } }
} catch (XmlException err) { // rssFeed.ErrorMessage = "Xml error: " + err.Message;
// Fire the error event if (this.Error != null) { RssReaderErrorEventArgs args = new RssReaderErrorEventArgs(); args.Message = rssFeed.ErrorMessage; this.Error(this, args); } return rssFeed; }
return rssFeed; }
/// <summary> /// Creates an RSS item from an XML node with the /// corresponding child nodes (title,description etc.) /// </summary> /// <param name="xmlNode">The node to extract the details from</param> /// <returns>An RssItem object with details taken from the item node.</returns> private RssItem getRssItem(XmlNode xmlNode) { RssItem rssItem = new RssItem();
for (int i = 0; i < xmlNode.ChildNodes.Count; i++) { switch (xmlNode.ChildNodes[i].Name.ToLower()) { case "title": { rssItem.Title = xmlNode.ChildNodes[i].InnerText; break; } case "description": { rssItem.Description = xmlNode.ChildNodes[i].InnerText; break; } case "link": { rssItem.Link = xmlNode.ChildNodes[i].InnerText; break; } case "author": { rssItem.Author = xmlNode.ChildNodes[i].InnerText; break; } case "comments": { rssItem.Comments = xmlNode.ChildNodes[i].InnerText; break; } case "pubdate": { rssItem.Pubdate = xmlNode.ChildNodes[i].InnerText; break; } case "guid": { rssItem.Guid = xmlNode.ChildNodes[i].InnerText; break; } } }
return rssItem; } } #endregion
#region Html creator class /// <summary> /// This class provides an easy method of converting a <see cref="RssFeed">RssFeed</see> /// object into a simple HTML document. This document can then be written to /// file, where it can be stored in a cached state (saving a feed request each /// time the feed is required). /// </summary> public class RssHtmlMaker {
/// <summary> /// Restricts the number of items that are displayed and replaced /// using the %Items% token in the HTML template. /// </summary> public int MaxItems { get { return this.maxItems; } set { this.maxItems = value; } }
/// <summary> /// Member for the public property. /// </summary> private int maxItems = 0;
/// <summary> /// Creates a HTML document, or any format - this is only limited by /// the template you provide - from the provided /// <see cref="RssFeed">RssFeed</see> object. The tokens described in the /// remarks section are replaced with their values inside the template. /// The items in the RSS feed are replaced using the ItemPrefix and ItemSuffix /// templates, where the suffix is placed face, and the suffix is appended on the end. /// </summary> /// <remarks> /// The following are a list of tokens which are replaced inside the main Template, /// with their corresponding values from the provided <see cref="RssFeed">RssFeed</see> /// object. For details on each token, see its corresponding property in the /// <see cref="RssFeed">RssFeed</see> object. /// <list type="bullet"> /// <item>%Title%</item> /// <item>%Description%</item> /// <item>%Link%</item> /// <item>%Language%</item> /// <item>%Copyright%</item> /// <item>%Webmaster%</item> /// <item>%PubDate%</item> /// <item>%LastBuildDate%</item> /// <item>%Category%</item> /// <item>%Generator%</item> /// <item>%Ttl%</item> /// <item>%Rating%</item> /// <item>%Skiphours%</item> /// <item>%Skipdays%</item> /// <item>%Skipdays%</item> /// <item>%Items% - This is replaced by the parsed template of the items</item> /// </list> /// The following are a list of tokens which are replaced inside the ItemPrefix /// and ItemSuffix templates, with their corresponding values from the /// provided <see cref="RssItem">RssItem</see> object. For details /// on each token, see its corresponding property in /// the <see cref="RssItem">RssItem</see> object. /// <list type="bullet"> /// <item>%Title%</item> /// <item>%Description%</item> /// <item>%Link%</item> /// <item>%Author%</item> /// <item>%Comments%</item> /// <item>%Pubdate%</item> /// <item>%Guid%</item> /// </list> /// </remarks> /// <param name="Feed">The <see cref="RssFeed">RssFeed</see> object to /// get the tokens' data from.</param> /// <param name="Template">The overall HTML template (or any other format) /// to replace the tokens in.</param> /// <param name="ItemPrefix">A string template that is prepended to the beginning /// of each RSS item.</param> /// <param name="ItemSuffix">A string template that is apppended to the end /// of each RSS item.</param> /// <returns>A string with the templates provided parsed of their tokens, with /// the data values in their place.</returns> public string GetHtmlContents(RssFeed Feed, string Template, string ItemPrefix, string ItemSuffix) { string result = Template;
// Replace all template tokens result = result.Replace("%Title%", Feed.Title); result = result.Replace("%Description%", Feed.Description); result = result.Replace("%Link%", Feed.Link); result = result.Replace("%Language%", Feed.Language); result = result.Replace("%Copyright%", Feed.Copyright); result = result.Replace("%Webmaster%", Feed.Webmaster); result = result.Replace("%PubDate%", Feed.PubDate); result = result.Replace("%LastBuildDate%", Feed.LastBuildDate); result = result.Replace("%Category%", Feed.Category); result = result.Replace("%Generator%", Feed.Generator); result = result.Replace("%Ttl%", Feed.Ttl); result = result.Replace("%Rating%", Feed.Rating); result = result.Replace("%Skiphours%", Feed.Skiphours); result = result.Replace("%Skipdays%", Feed.Skipdays); result = result.Replace("%Skipdays%", Feed.ManagingEditor);
// Parse item template string itemsContent = ""; string tempContent = "";
if (maxItems == 0 || maxItems > Feed.Items.Count) { maxItems = Feed.Items.Count; }
for (int i = 0; i < maxItems; i++) { // Parse prefix template tempContent = ItemPrefix; tempContent = tempContent.Replace("%Title%", Feed.Items[i].Title); tempContent = tempContent.Replace("%Description%", Feed.Items[i].Description); tempContent = tempContent.Replace("%Link%", Feed.Items[i].Link); tempContent = tempContent.Replace("%Author%", Feed.Items[i].Author); tempContent = tempContent.Replace("%Comments%", Feed.Items[i].Comments); tempContent = tempContent.Replace("%Pubdate%", Feed.Items[i].Pubdate); tempContent = tempContent.Replace("%Guid%", Feed.Items[i].Guid);
itemsContent += tempContent;
// Parse suffix template tempContent = ItemSuffix; tempContent = tempContent.Replace("%Title%", Feed.Items[i].Title); tempContent = tempContent.Replace("%Description%", Feed.Items[i].Description); tempContent = tempContent.Replace("%Link%", Feed.Items[i].Link); tempContent = tempContent.Replace("%Author%", Feed.Items[i].Author); tempContent = tempContent.Replace("%Comments%", Feed.Items[i].Comments); tempContent = tempContent.Replace("%Pubdate%", Feed.Items[i].Pubdate); tempContent = tempContent.Replace("%Guid%", Feed.Items[i].Guid);
itemsContent += tempContent; }
// Replace %items% with items result = result.Replace("%Items%", itemsContent);
return result; } } #endregion
#region Data structures /// <summary> /// A data type to represent all properties of single RSS feed. /// (one XML document). The descriptions for /// the properties of RssItem are para-phrased from the /// <see href="http://blogs.law.harvard.edu/tech/rss">RSS 2 specification</see>. /// See <see cref="RssReader">RssReader</see> for properties which /// have not yet been implemented in this version of the /// the RssReader class. /// </summary> /// <remarks> /// The following elements of the RSS <channel> node aren't /// supported by this version of RssReader: /// <list type="bullet"> /// <item>image (has subelements: image,url,title,link)</item> /// <item>cloud (has attributes: domain,port,path,registerProcedure,protocol)</item> /// <item>textInput (has subelements: title,description,name,link)</item> /// </list> /// </remarks> [Serializable()] public struct RssFeed { /// <summary> /// The name of the channel. /// </summary> public string Title; /// <summary> /// Phrase or sentence describing the channel. /// </summary> public string Description; /// <summary> /// The URL to the HTML website corresponding to the channel. /// </summary> public string Link;
// Optional items
/// <summary> /// The language the channel is written in. This allows /// aggregators to group all Italian language sites, for example, on a single page. /// </summary> public string Language; /// <summary> /// Copyright notice for content in the channel. /// </summary> public string Copyright; /// <summary> /// Email address for person responsible for technical issues relating to channel. /// </summary> public string Webmaster; /// <summary> /// The publication date for the content in the channel. /// </summary> public string PubDate; /// <summary> /// The last time the content of the channel changed. /// </summary> public string LastBuildDate; /// <summary> /// Specify one or more categories that the channel belongs to. /// </summary> public string Category; /// <summary> /// A string indicating the program used to generate the channel. /// </summary> public string Generator; /// <summary> /// ttl stands for time to live. It's a number of minutes /// that indicates how long a channel can be cached before /// refreshing from the source /// </summary> public string Ttl; /// <summary> /// The <see href="http://www.w3.org/PICS/">PICS</see> rating for the channel. /// </summary> public string Rating; /// <summary> /// A hint for aggregators telling them which hours they can skip. /// </summary> public string Skiphours; /// <summary> /// A hint for aggregators telling them which days they can skip. /// </summary> public string Skipdays; /// <summary> /// Email address for person responsible for editorial content. /// </summary> public string ManagingEditor; /// <summary> /// A collection of RssItem datatypes, representing each /// item for the RSS feed. /// </summary> public RssItems Items; /// <summary> /// Contains any errors that occured during the loading or /// parsing of the XML document. Compare this to a blank string /// to see if any errors occured. /// </summary> public string ErrorMessage; }
/// <summary> /// A data type to represent a single /// RSS item in a RSS feed. See <see cref="RssReader">RssReader</see> for /// properties of a RSS item which have not yet been implemented /// in this version of the the RssReader class. The descriptions for /// the properties of RssItem are para-phrased from the /// <see href="http://blogs.law.harvard.edu/tech/rss">RSS 2 specification.</see> /// </summary> /// <remarks> /// The following elements of a RSS item aren't /// supported by this version of RssReader: /// <list type="bullet"> /// <item>category (can have domain attribute)</item> /// <item>enclosure ( has attributes: url,length,type )</item> /// <item>source (has attributes: url)</item> /// </list> /// </remarks> [Serializable()] public struct RssItem { /// <summary> /// The title of the item. /// </summary> public string Title; /// <summary> /// The item synopsis. /// </summary> public string Description; /// <summary> /// The URL of the item. /// </summary> public string Link; /// <summary> /// Email address of the author of the item. /// </summary> public string Author; /// <summary> /// URL of a page for comments relating to the item /// </summary> public string Comments; /// <summary> /// Indicates when the item was published. /// </summary> public string Pubdate; /// <summary> /// A string that uniquely identifies the item. /// </summary> public string Guid; }
/// <summary> /// Represents a collection of RSS items for /// the RSS feed. /// </summary> [Serializable()] public class RssItems : CollectionBase { public RssItem this[int item] { get { return this.getItem(item); } }
public void Add(RssItem rssItem) { List.Add(rssItem); }
public bool Remove(int index) { if (index > Count - 1 || index < 0) { return false; } else { List.RemoveAt(index); return true; } }
private RssItem getItem(int Index) { return (RssItem)List[Index]; }
} #endregion
}