RssFeed Retrieve: Difference between revisions
From ICO wiki
Jump to navigationJump to search
No edit summary |
No edit summary |
||
Line 1: | Line 1: | ||
RSS voogu uudiste nimekiri kätte saamine (abi klass) | |||
<source lang=csharp> | <source lang=csharp> | ||
using System; | using System; |
Latest revision as of 14:10, 16 April 2010
RSS voogu uudiste nimekiri kätte saamine (abi klass)
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.
/// <code>
/// 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);
/// }
/// </code>
/// </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
}