private void OnElementElementCompleted(RssElement e) { ElementsChanged?.Invoke(e, EventArgs.Empty); if (Elements.Where(r => r.Completed == false).FirstOrDefault() == null) { LoadCompleted?.Invoke(this, EventArgs.Empty); } }
private async Task Fetch(Category category) { var rssElement = new RssElement { Category = category, EndPoint = new Uri(string.Format(ARTICLE_URI, category.Id)) }; try { var xmlDocument = await XmlDocument.LoadFromUriAsync(rssElement.EndPoint); var channelNode = xmlDocument.LastChild?.SelectSingleNode("channel"); if (channelNode != null) { rssElement.Category.Title = channelNode.SelectSingleNode("title")?.InnerText; rssElement.Category.Copyright = channelNode.SelectSingleNode("copyright")?.InnerText; rssElement.Category.Language = channelNode.SelectSingleNode("language")?.InnerText; rssElement.Category.Description = channelNode.SelectSingleNode("description")?.InnerText; rssElement.Category.Link = new Uri(channelNode.SelectSingleNode("link")?.InnerText); rssElement.Articles = new List <Article>(); foreach (var item in channelNode.SelectNodes("item")) { var article = new Article { Category = rssElement.Category, Title = item.SelectSingleNode("title")?.InnerText, Description = item.SelectSingleNode("description")?.InnerText, Link = new Uri(item.SelectSingleNode("link")?.InnerText), PubDate = DateTime.Parse(item.SelectSingleNode("pubDate")?.InnerText) }; article.Id = int.Parse(article.Link.ToString().Replace(ID_PATTERN, string.Empty).Split('-').First()); rssElement.Articles.Add(article); if (!Articles.Any(a => a.Link.Equals(article.Link))) { Articles.Add(article); } } _elements.Add(rssElement); } } catch (Exception exception) { Debug.WriteLine(exception.Message); } }
private async void Load(Uri uri, Category c) { RssElement e = new RssElement() { Category = c, EndPoint = uri }; Elements.Add(e); await e.Fetch(); e.Completed = true; OnElementElementCompleted(e); }
public void Display(string url) { if (string.IsNullOrEmpty(url)) { throw new ArgumentException("Null RssFeedUrl"); } RssFeed feed = null; if (HttpContext.Current.Cache.Get(RSS_CACHE_NAME) == null) { feed = RssFeed.Read(url); HttpContext.Current.Cache.Add(RSS_CACHE_NAME, feed, null, DateTime.Now.AddDays(1), TimeSpan.Zero, System.Web.Caching.CacheItemPriority.Default, null); } else { feed = HttpContext.Current.Cache.Get(RSS_CACHE_NAME) as RssFeed; } // Limit feed to the first 4 elements: if ((feed.Channels != null) && (feed.Channels.Count > 0)) { for (int i = feed.Channels.Count - 1; i > 3; --i) { feed.Channels.RemoveAt(i); } RssItemCollection items = feed.Channels[0].Items; if ((items != null) && (items.Count > 0)) { for (int i = items.Count - 1; i > 3; --i) { RssElement element = items[i]; items.RemoveAt(i); } } } listChannels.DataSource = feed.Channels; listChannels.DataBind(); }
private static RssFeed read(string url, HttpWebRequest request, RssFeed oldFeed) { // ***** Marked for substantial improvement RssFeed feed = new RssFeed(); Stream stream = null; Uri uri = new Uri(url); feed.url = url; switch (uri.Scheme) { case "file": feed.lastModified = File.GetLastWriteTime(url); if ((oldFeed != null) && (feed.LastModified == oldFeed.LastModified)) { oldFeed.cached = true; return(oldFeed); } stream = new FileStream(url, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); break; case "https": case "http": if (request == null) { request = (HttpWebRequest)WebRequest.Create(uri); request.Proxy = WebProxy.GetDefaultProxy(); request.Proxy.Credentials = CredentialCache.DefaultCredentials; } if (oldFeed != null) { request.IfModifiedSince = oldFeed.LastModified; request.Headers.Add("If-None-Match", oldFeed.ETag); } try { HttpWebResponse response = (HttpWebResponse)request.GetResponse(); feed.lastModified = response.LastModified; feed.etag = response.Headers["ETag"]; try { if (response.ContentEncoding != String.Empty) { feed.encoding = Encoding.GetEncoding(response.ContentEncoding); } } catch { } stream = response.GetResponseStream(); } catch (WebException we) { if (oldFeed != null) { oldFeed.cached = true; return(oldFeed); } throw we; // bad } break; } if (stream != null) { RssReader reader = null; try { reader = new RssReader(stream); RssElement element = null; do { element = reader.Read(); if (element is RssChannel.RssChannel) { feed.Channels.Add((RssChannel.RssChannel)element); } } while (element != null); feed.rssVersion = reader.Version; } finally { feed.exceptions = reader.Exceptions; reader.Close(); } } else { throw new ApplicationException("Not a valid Url"); } return(feed); }
/// <summary> /// Reads the next RssElement from the stream. /// </summary> /// <returns> An RSS Element </returns> /// <exception cref="InvalidOperationException">RssReader has been closed, and can not be read.</exception> /// <exception cref="System.IO.FileNotFoundException">RSS file not found.</exception> /// <exception cref="System.Xml.XmlException">Invalid XML syntax in RSS file.</exception> /// <exception cref="System.IO.EndOfStreamException">Unable to read an RssElement. Reached the end of the stream.</exception> public RssElement Read() { bool readData = false; RssElement rssElement = null; int lineNumber = -1; int linePosition = -1; if (this.reader == null) { throw new InvalidOperationException("RssReader has been closed, and can not be read."); } do { bool pushElement = true; try { readData = this.reader.Read(); } catch (EndOfStreamException e) { throw new EndOfStreamException("Unable to read an RssElement. Reached the end of the stream.", e); } catch (XmlException e) { if (lineNumber != -1 || linePosition != -1) { if (this.reader.LineNumber == lineNumber && this.reader.LinePosition == linePosition) { throw this.exceptions.LastException; } } lineNumber = this.reader.LineNumber; linePosition = this.reader.LinePosition; this.exceptions.Add(e); // just add to list of exceptions and continue :) } if (readData) { string readerName = this.reader.Name.ToLower(); switch (this.reader.NodeType) { case XmlNodeType.Element: { //if (reader.IsEmptyElement) // break; // doesnt take empty elements into account :/ this.elementText = new StringBuilder(); switch (readerName) { case "item": // is this the end of the channel element? (absence of </channel> before <item>) if (!this.wroteChannel) { this.wroteChannel = true; rssElement = this.channel; // return RssChannel readData = false; } this.item = new RssItem.RssItem(); // create new RssItem this.channel.Items.Add(this.item); break; case "source": this.source = new RssSource(); this.item.Source = this.source; for (int i = 0; i < this.reader.AttributeCount; i++) { this.reader.MoveToAttribute(i); switch (this.reader.Name.ToLower()) { case "url": try { this.source.Url = new Uri(this.reader.Value); } catch (Exception e) { this.exceptions.Add(e); } break; } } break; case "enclosure": this.enclosure = new RssEnclosure(); this.item.Enclosure = this.enclosure; for (int i = 0; i < this.reader.AttributeCount; i++) { this.reader.MoveToAttribute(i); switch (this.reader.Name.ToLower()) { case "url": try { this.enclosure.Url = new Uri(this.reader.Value); } catch (Exception e) { this.exceptions.Add(e); } break; case "length": try { this.enclosure.Length = int.Parse(this.reader.Value); } catch (Exception e) { this.exceptions.Add(e); } break; case "type": this.enclosure.Type = this.reader.Value; break; } } break; case "guid": this.guid = new RssGuid(); this.item.Guid = this.guid; for (int i = 0; i < this.reader.AttributeCount; i++) { this.reader.MoveToAttribute(i); switch (this.reader.Name.ToLower()) { case "ispermalink": try { this.guid.PermaLink = bool.Parse(this.reader.Value); } catch (Exception e) { this.exceptions.Add(e); } break; } } break; case "category": this.category = new RssCategory(); if ((string)this.xmlNodeStack.Peek() == "channel") { this.channel.Categories.Add(this.category); } else { this.item.Categories.Add(this.category); } for (int i = 0; i < this.reader.AttributeCount; i++) { this.reader.MoveToAttribute(i); switch (this.reader.Name.ToLower()) { case "url": goto case "domain"; case "domain": this.category.Domain = this.reader.Value; break; } } break; case "channel": this.channel = new RssChannel.RssChannel(); this.textInput = null; this.image = null; this.cloud = null; this.source = null; this.enclosure = null; this.category = null; this.item = null; break; case "image": this.image = new RssImage(); this.channel.Image = this.image; break; case "textinput": this.textInput = new RssTextInput(); this.channel.TextInput = this.textInput; break; case "cloud": pushElement = false; this.cloud = new RssCloud(); this.channel.Cloud = this.cloud; for (int i = 0; i < this.reader.AttributeCount; i++) { this.reader.MoveToAttribute(i); switch (this.reader.Name.ToLower()) { case "domain": this.cloud.Domain = this.reader.Value; break; case "port": try { this.cloud.Port = ushort.Parse(this.reader.Value); } catch (Exception e) { this.exceptions.Add(e); } break; case "path": this.cloud.Path = this.reader.Value; break; case "registerprocedure": this.cloud.RegisterProcedure = this.reader.Value; break; case "protocol": switch (this.reader.Value.ToLower()) { case "xml-rpc": this.cloud.Protocol = RssCloudProtocol.XmlRpc; break; case "soap": this.cloud.Protocol = RssCloudProtocol.Soap; break; case "http-post": this.cloud.Protocol = RssCloudProtocol.HttpPost; break; default: this.cloud.Protocol = RssCloudProtocol.Empty; break; } break; } } break; case "rss": for (int i = 0; i < this.reader.AttributeCount; i++) { this.reader.MoveToAttribute(i); if (this.reader.Name.ToLower() == "version") { switch (this.reader.Value) { case "0.91": this.rssVersion = RssVersion.RSS091; break; case "0.92": this.rssVersion = RssVersion.RSS092; break; case "2.0": this.rssVersion = RssVersion.RSS20; break; default: this.rssVersion = RssVersion.NotSupported; break; } } } break; case "rdf": for (int i = 0; i < this.reader.AttributeCount; i++) { this.reader.MoveToAttribute(i); if (this.reader.Name.ToLower() == "version") { switch (this.reader.Value) { case "0.90": this.rssVersion = RssVersion.RSS090; break; case "1.0": this.rssVersion = RssVersion.RSS10; break; default: this.rssVersion = RssVersion.NotSupported; break; } } } break; } if (pushElement) { this.xmlNodeStack.Push(readerName); } break; } case XmlNodeType.EndElement: { if (this.xmlNodeStack.Count == 1) { break; } string childElementName = (string)this.xmlNodeStack.Pop(); string parentElementName = (string)this.xmlNodeStack.Peek(); switch (childElementName) // current element { // item classes case "item": rssElement = this.item; readData = false; break; case "source": this.source.Name = this.elementText.ToString(); rssElement = this.source; readData = false; break; case "enclosure": rssElement = this.enclosure; readData = false; break; case "guid": this.guid.Name = this.elementText.ToString(); rssElement = this.guid; readData = false; break; case "category": // parent is either item or channel this.category.Name = this.elementText.ToString(); rssElement = this.category; readData = false; break; // channel classes case "channel": if (this.wroteChannel) { this.wroteChannel = false; } else { this.wroteChannel = true; rssElement = this.channel; readData = false; } break; case "textinput": rssElement = this.textInput; readData = false; break; case "image": rssElement = this.image; readData = false; break; case "cloud": rssElement = this.cloud; readData = false; break; } switch (parentElementName) // parent element { case "item": switch (childElementName) { case "title": this.item.Title = this.elementText.ToString(); break; case "link": this.item.Link = new Uri(this.elementText.ToString()); break; case "description": this.item.Description = this.elementText.ToString(); break; case "author": this.item.Author = this.elementText.ToString(); break; case "comments": this.item.Comments = this.elementText.ToString(); break; case "pubdate": try { this.item.PubDate = DateTime.Parse(this.elementText.ToString()); } catch (Exception e) { try { string tmp = this.elementText.ToString(); tmp = tmp.Substring(0, tmp.Length - 5); tmp += "GMT"; this.item.PubDate = DateTime.Parse(tmp); } catch { this.exceptions.Add(e); } } break; } break; case "channel": switch (childElementName) { case "title": this.channel.Title = this.elementText.ToString(); break; case "link": try { this.channel.Link = new Uri(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; case "description": this.channel.Description = this.elementText.ToString(); break; case "language": this.channel.Language = this.elementText.ToString(); break; case "copyright": this.channel.Copyright = this.elementText.ToString(); break; case "managingeditor": this.channel.ManagingEditor = this.elementText.ToString(); break; case "webmaster": this.channel.WebMaster = this.elementText.ToString(); break; case "rating": this.channel.Rating = this.elementText.ToString(); break; case "pubdate": try { this.channel.PubDate = DateTime.Parse(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; case "lastbuilddate": try { this.channel.LastBuildDate = DateTime.Parse(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; case "generator": this.channel.Generator = this.elementText.ToString(); break; case "docs": this.channel.Docs = this.elementText.ToString(); break; case "ttl": try { this.channel.TimeToLive = int.Parse(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; } break; case "image": switch (childElementName) { case "url": try { this.image.Url = new Uri(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; case "title": this.image.Title = this.elementText.ToString(); break; case "link": try { this.image.Link = new Uri(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; case "description": this.image.Description = this.elementText.ToString(); break; case "width": try { this.image.Width = Byte.Parse(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; case "height": try { this.image.Height = Byte.Parse(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; } break; case "textinput": switch (childElementName) { case "title": this.textInput.Title = this.elementText.ToString(); break; case "description": this.textInput.Description = this.elementText.ToString(); break; case "name": this.textInput.Name = this.elementText.ToString(); break; case "link": try { this.textInput.Link = new Uri(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; } break; case "skipdays": if (childElementName == "day") { switch (this.elementText.ToString().ToLower()) { case "monday": this.channel.SkipDays[0] = true; break; case "tuesday": this.channel.SkipDays[1] = true; break; case "wednesday": this.channel.SkipDays[2] = true; break; case "thursday": this.channel.SkipDays[3] = true; break; case "friday": this.channel.SkipDays[4] = true; break; case "saturday": this.channel.SkipDays[5] = true; break; case "sunday": this.channel.SkipDays[6] = true; break; } } break; case "skiphours": if (childElementName == "hour") { this.channel.SkipHours[Byte.Parse(this.elementText.ToString().ToLower())] = true; } break; } break; } case XmlNodeType.Text: this.elementText.Append(this.reader.Value); break; case XmlNodeType.CDATA: this.elementText.Append(this.reader.Value); break; } } } while (readData); return(rssElement); }