PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/Growl Extras/Feed Monitor/GrowlExtras.FeedMonitor/_source/Rss10FeedFormatter.cs

http://growl-for-windows.googlecode.com/
C# | 278 lines | 223 code | 53 blank | 2 comment | 86 complexity | 860dce086412dbb477b46dc0f5f1f6a1 MD5 | raw file
Possible License(s): BSD-2-Clause, CC-BY-3.0
  1. using System;
  2. using System.Collections.ObjectModel;
  3. using System.Xml;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Text;
  7. using System.ServiceModel.Syndication;
  8. namespace GrowlExtras.FeedMonitor
  9. {
  10. public class Rss10FeedFormatter : SyndicationFeedFormatter
  11. {
  12. #region Constructors
  13. public Rss10FeedFormatter() { }
  14. public Rss10FeedFormatter(SyndicationFeed feed) : base(feed) { }
  15. #endregion
  16. #region Properties
  17. public override string Version
  18. {
  19. get { return "Rss10"; }
  20. }
  21. public virtual string RdfNamespaceUri
  22. {
  23. get { return "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; }
  24. }
  25. public virtual string NamespaceUri
  26. {
  27. get { return "http://purl.org/rss/1.0/"; }
  28. }
  29. #endregion
  30. #region Methods
  31. #region Read XML Methods
  32. public override bool CanRead(System.Xml.XmlReader reader)
  33. {
  34. if (reader == null)
  35. throw new ArgumentNullException("reader");
  36. return reader.IsStartElement("RDF", this.RdfNamespaceUri);
  37. }
  38. protected override SyndicationFeed CreateFeedInstance()
  39. {
  40. return new SyndicationFeed();
  41. }
  42. public override void ReadFrom(System.Xml.XmlReader reader)
  43. {
  44. if (!this.CanRead(reader))
  45. throw new XmlException("Unknown RSS 1.0 feed format.");
  46. this.ReadFeed(reader);
  47. }
  48. private void ReadFeed(XmlReader reader)
  49. {
  50. this.SetFeed(this.CreateFeedInstance());
  51. this.ReadXml(reader, base.Feed);
  52. }
  53. protected virtual void ReadXml(XmlReader reader, SyndicationFeed result)
  54. {
  55. if (result == null)
  56. throw new ArgumentNullException("result");
  57. else if (reader == null)
  58. throw new ArgumentNullException("reader");
  59. reader.ReadStartElement(); // Read in <RDF>
  60. reader.ReadStartElement("channel"); // Read in <channel>
  61. while (reader.IsStartElement()) // Process <channel> children
  62. {
  63. if (reader.IsStartElement("title"))
  64. result.Title = new TextSyndicationContent(reader.ReadElementString());
  65. else if (reader.IsStartElement("link"))
  66. result.Links.Add(new SyndicationLink(new Uri(reader.ReadElementString())));
  67. else if (reader.IsStartElement("description"))
  68. result.Description = new TextSyndicationContent(reader.ReadElementString());
  69. else
  70. reader.Skip();
  71. }
  72. reader.ReadEndElement(); // Read in </channel>
  73. while (reader.IsStartElement())
  74. {
  75. if (reader.IsStartElement("item"))
  76. {
  77. result.Items = this.ReadItems(reader, result);
  78. break;
  79. }
  80. else
  81. reader.Skip();
  82. }
  83. }
  84. protected virtual IEnumerable<SyndicationItem> ReadItems(XmlReader reader, SyndicationFeed feed)
  85. {
  86. if (feed == null)
  87. throw new ArgumentNullException("feed");
  88. else if (reader == null)
  89. throw new ArgumentNullException("reader");
  90. Collection<SyndicationItem> items = new Collection<SyndicationItem>();
  91. while (reader.IsStartElement("item"))
  92. {
  93. items.Add(this.ReadItem(reader, feed));
  94. }
  95. return items;
  96. }
  97. protected virtual SyndicationItem ReadItem(XmlReader reader, SyndicationFeed feed)
  98. {
  99. if (feed == null)
  100. throw new ArgumentNullException("feed");
  101. else if (reader == null)
  102. throw new ArgumentNullException("reader");
  103. SyndicationItem result = new SyndicationItem();
  104. this.ReadItemFrom(reader, result);
  105. return result;
  106. }
  107. protected virtual void ReadItemFrom(XmlReader reader, SyndicationItem result)
  108. {
  109. if (result == null)
  110. throw new ArgumentNullException("result");
  111. else if (reader == null)
  112. throw new ArgumentNullException("reader");
  113. reader.ReadStartElement();
  114. while (reader.IsStartElement())
  115. {
  116. if (reader.IsStartElement("title"))
  117. result.Title = new TextSyndicationContent(reader.ReadElementString());
  118. else if (reader.IsStartElement("link"))
  119. result.Links.Add(new SyndicationLink(new Uri(reader.ReadElementString())));
  120. else if (reader.IsStartElement("description"))
  121. result.Summary = new TextSyndicationContent(reader.ReadElementString());
  122. else
  123. reader.Skip();
  124. }
  125. reader.ReadEndElement();
  126. }
  127. #endregion
  128. #region Write XML Methods
  129. public override void WriteTo(System.Xml.XmlWriter writer)
  130. {
  131. if (writer == null)
  132. throw new ArgumentNullException("writer");
  133. writer.WriteStartElement("rdf", "RDF", this.RdfNamespaceUri); // Write <RDF>
  134. writer.WriteAttributeString("xmlns", this.NamespaceUri);
  135. this.WriteFeed(writer);
  136. writer.WriteEndElement();
  137. }
  138. protected virtual void WriteFeed(XmlWriter writer)
  139. {
  140. if (writer == null)
  141. throw new ArgumentNullException("writer");
  142. if (base.Feed == null)
  143. throw new InvalidOperationException("Feed formatter does not have a feed.");
  144. string alternateLink = string.Empty, selfLink = string.Empty;
  145. foreach (SyndicationLink lnk in base.Feed.Links)
  146. {
  147. if (alternateLink.Length == 0 && lnk.RelationshipType == "alternate")
  148. alternateLink = lnk.Uri.IsAbsoluteUri ? lnk.Uri.AbsoluteUri : lnk.Uri.ToString();
  149. else if (selfLink.Length == 0 && lnk.RelationshipType == "self")
  150. selfLink = lnk.Uri.IsAbsoluteUri ? lnk.Uri.AbsoluteUri : lnk.Uri.ToString();
  151. }
  152. if (selfLink.Length == 0 && alternateLink.Length > 0)
  153. selfLink = alternateLink;
  154. else if (alternateLink.Length == 0 && selfLink.Length > 0)
  155. alternateLink = selfLink;
  156. writer.WriteStartElement("channel"); // Write <channel>
  157. writer.WriteAttributeString("about", this.RdfNamespaceUri, selfLink);
  158. if (base.Feed.Title == null || string.IsNullOrEmpty(base.Feed.Title.Text))
  159. throw new ArgumentException("Feed title required for RSS 1.0 feeds.");
  160. writer.WriteElementString("title", base.Feed.Title.Text); // Write <title>
  161. if (alternateLink.Length == 0)
  162. throw new ArgumentException("Feed link required for RSS 1.0 feeds.");
  163. writer.WriteElementString("link", alternateLink); // Write <link>
  164. if (base.Feed.Description == null || string.IsNullOrEmpty(base.Feed.Description.Text))
  165. throw new ArgumentException("Feed title required for RSS 1.0 feeds.");
  166. writer.WriteElementString("description", base.Feed.Description.Text); // Write <description>
  167. writer.WriteStartElement("items"); // Write <items>
  168. writer.WriteStartElement("Seq", this.RdfNamespaceUri);
  169. foreach (SyndicationItem item in base.Feed.Items)
  170. {
  171. string itemAlternateLink = GetAlternateLinkForItem(item);
  172. writer.WriteStartElement("li", this.RdfNamespaceUri);
  173. writer.WriteAttributeString("resource", this.RdfNamespaceUri, itemAlternateLink);
  174. writer.WriteEndElement();
  175. }
  176. writer.WriteEndElement();
  177. writer.WriteEndElement();
  178. writer.WriteEndElement(); // Write </channel>
  179. // Write the <item> elements
  180. this.WriteItems(writer, base.Feed.Items);
  181. }
  182. protected virtual void WriteItems(XmlWriter writer, IEnumerable<SyndicationItem> items)
  183. {
  184. if (writer == null)
  185. throw new ArgumentNullException("writer");
  186. if (items != null)
  187. foreach (SyndicationItem item in items)
  188. this.WriteItem(writer, item);
  189. }
  190. protected virtual void WriteItem(XmlWriter writer, SyndicationItem item)
  191. {
  192. if (writer == null)
  193. throw new ArgumentNullException("writer");
  194. string alternateLink = GetAlternateLinkForItem(item);
  195. writer.WriteStartElement("item"); // Write <item>
  196. writer.WriteAttributeString("about", this.RdfNamespaceUri, alternateLink);
  197. this.WriteItemContents(writer, item);
  198. writer.WriteEndElement();
  199. }
  200. protected virtual void WriteItemContents(XmlWriter writer, SyndicationItem item)
  201. {
  202. if (writer == null)
  203. throw new ArgumentNullException("writer");
  204. if (item.Title == null || string.IsNullOrEmpty(item.Title.Text))
  205. throw new ArgumentException("Feed title required for RSS 1.0 feeds.");
  206. writer.WriteElementString("title", item.Title.Text); // Write <title>
  207. string alternateLink = GetAlternateLinkForItem(item);
  208. if (string.IsNullOrEmpty(alternateLink))
  209. throw new ArgumentException("Feed link required for RSS 1.0 feeds.");
  210. writer.WriteElementString("link", alternateLink); // Write <link>
  211. if (base.Feed.Description != null && string.IsNullOrEmpty(item.Summary.Text) == false)
  212. writer.WriteElementString("description", item.Summary.Text); // Write the optional <description>
  213. }
  214. private string GetAlternateLinkForItem(SyndicationItem item)
  215. {
  216. foreach (SyndicationLink lnk in item.Links)
  217. if (lnk.RelationshipType == "alternate")
  218. return lnk.Uri.IsAbsoluteUri ? lnk.Uri.AbsoluteUri : lnk.Uri.ToString();
  219. // If we reach here, return an empty string
  220. return string.Empty;
  221. }
  222. #endregion
  223. #endregion
  224. }
  225. }