/// <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; bool pushElement = true; RssElement rssElement = null; int lineNumber = -1; int linePosition = -1; if (reader == null) { throw new InvalidOperationException("RssReader has been closed, and can not be read."); } do { pushElement = true; try { readData = reader.Read(); } catch (System.IO.EndOfStreamException e) { throw new System.IO.EndOfStreamException("Unable to read an RssElement. Reached the end of the stream.", e); } catch (System.Xml.XmlException e) { if (lineNumber != -1 || linePosition != -1) { if (reader.LineNumber == lineNumber && reader.LinePosition == linePosition) { throw exceptions.LastException; } } lineNumber = reader.LineNumber; linePosition = reader.LinePosition; exceptions.Add(e); // just add to list of exceptions and continue :) //// Added, OFxP //if (readData) //{ // continue; //} } if (readData) { string readerName = reader.Name.ToLower(); switch (reader.NodeType) { case XmlNodeType.Element: { if (reader.IsEmptyElement) { break; } elementText = new StringBuilder(); switch (readerName) { case "item": // is this the end of the channel element? (absence of </channel> before <item>) if (!wroteChannel) { wroteChannel = true; rssElement = channel; // return RssChannel readData = false; } item = new RssItem(); // create new RssItem channel.Items.Add(item); break; case "source": source = new RssSource(); item.Source = source; for (int i = 0; i < reader.AttributeCount; i++) { reader.MoveToAttribute(i); switch (reader.Name.ToLower()) { case "url": try { // OFxP, fix //source.Url = new Uri(reader.Value); source.Url = new Uri(reader.Value, true); } catch (Exception e) { exceptions.Add(e); } break; } } break; case "enclosure": enclosure = new RssEnclosure(); item.Enclosure = enclosure; for (int i = 0; i < reader.AttributeCount; i++) { reader.MoveToAttribute(i); switch (reader.Name.ToLower()) { case "url": try { // OFxP, fix //enclosure.Url = new Uri(reader.Value); enclosure.Url = new Uri(reader.Value, true); } catch (Exception e) { exceptions.Add(e); } break; case "length": try { enclosure.Length = int.Parse(reader.Value); } catch (Exception e) { exceptions.Add(e); } break; case "type": enclosure.Type = reader.Value; break; } } break; case "guid": guid = new RssGuid(); item.Guid = guid; for (int i = 0; i < reader.AttributeCount; i++) { reader.MoveToAttribute(i); switch (reader.Name.ToLower()) { case "ispermalink": try { guid.PermaLink = bool.Parse(reader.Value); } catch (Exception e) { exceptions.Add(e); } break; } } break; case "category": category = new RssCategory(); if ((string)xmlNodeStack.Peek() == "channel") { channel.Categories.Add(category); } else { item.Categories.Add(category); } for (int i = 0; i < reader.AttributeCount; i++) { reader.MoveToAttribute(i); switch (reader.Name.ToLower()) { case "url": goto case "domain"; case "domain": category.Domain = reader.Value; break; } } break; case "channel": channel = new RssChannel(); textInput = null; image = null; cloud = null; source = null; enclosure = null; category = null; item = null; break; case "image": image = new RssImage(); channel.Image = image; break; case "textinput": textInput = new RssTextInput(); channel.TextInput = textInput; break; case "cloud": pushElement = false; cloud = new RssCloud(); channel.Cloud = cloud; for (int i = 0; i < reader.AttributeCount; i++) { reader.MoveToAttribute(i); switch (reader.Name.ToLower()) { case "domain": cloud.Domain = reader.Value; break; case "port": try { cloud.Port = ushort.Parse(reader.Value); } catch (Exception e) { exceptions.Add(e); } break; case "path": cloud.Path = reader.Value; break; case "registerprocedure": cloud.RegisterProcedure = reader.Value; break; case "protocol": switch (reader.Value.ToLower()) { case "xml-rpc": cloud.Protocol = RssCloudProtocol.XmlRpc; break; case "soap": cloud.Protocol = RssCloudProtocol.Soap; break; case "http-post": cloud.Protocol = RssCloudProtocol.HttpPost; break; default: cloud.Protocol = RssCloudProtocol.Empty; break; } break; } } break; case "rss": for (int i = 0; i < reader.AttributeCount; i++) { reader.MoveToAttribute(i); if (reader.Name.ToLower() == "version") { switch (reader.Value) { case "0.91": rssVersion = RssVersion.RSS091; break; case "0.92": rssVersion = RssVersion.RSS092; break; case "2.0": rssVersion = RssVersion.RSS20; break; default: rssVersion = RssVersion.NotSupported; break; } } } break; case "rdf": for (int i = 0; i < reader.AttributeCount; i++) { reader.MoveToAttribute(i); if (reader.Name.ToLower() == "version") { switch (reader.Value) { case "0.90": rssVersion = RssVersion.RSS090; break; case "1.0": rssVersion = RssVersion.RSS10; break; default: rssVersion = RssVersion.NotSupported; break; } } } break; } if (pushElement) { xmlNodeStack.Push(readerName); } break; } case XmlNodeType.EndElement: { if (xmlNodeStack.Count == 1) { break; } string childElementName = (string)xmlNodeStack.Pop(); string parentElementName = (string)xmlNodeStack.Peek(); switch (childElementName) // current element { // item classes case "item": rssElement = item; readData = false; break; case "source": source.Name = elementText.ToString(); rssElement = source; readData = false; break; case "enclosure": rssElement = enclosure; readData = false; break; case "guid": guid.Name = elementText.ToString(); rssElement = guid; readData = false; break; case "category": // parent is either item or channel category.Name = elementText.ToString(); rssElement = category; readData = false; break; // channel classes case "channel": if (wroteChannel) { wroteChannel = false; } else { wroteChannel = true; rssElement = channel; readData = false; } break; case "textinput": rssElement = textInput; readData = false; break; case "image": rssElement = image; readData = false; break; case "cloud": rssElement = cloud; readData = false; break; } switch (parentElementName) // parent element { case "item": switch (childElementName) { case "title": item.Title = elementText.ToString(); break; case "link": // OFxP, fix //item.Link = new Uri(elementText.ToString()); item.Link = new Uri(elementText.ToString(), true); break; case "description": item.Description = elementText.ToString(); break; case "author": item.Author = elementText.ToString(); break; case "comments": item.Comments = elementText.ToString(); break; case "pubdate": item.PubDate = GeneralHelper.ParseDateTimeWithZone(elementText.ToString()); break; } break; case "channel": switch (childElementName) { case "title": channel.Title = elementText.ToString(); break; case "link": try { // OFxP, fix //channel.Link = new Uri(elementText.ToString()); channel.Link = new Uri(elementText.ToString(), true); } catch (Exception e) { exceptions.Add(e); } break; case "description": channel.Description = elementText.ToString(); break; case "language": channel.Language = elementText.ToString(); break; case "copyright": channel.Copyright = elementText.ToString(); break; case "managingeditor": channel.ManagingEditor = elementText.ToString(); break; case "webmaster": channel.WebMaster = elementText.ToString(); break; case "rating": channel.Rating = elementText.ToString(); break; case "pubdate": channel.PubDate = GeneralHelper.ParseDateTimeWithZone(elementText.ToString()); break; case "lastbuilddate": channel.LastBuildDate = GeneralHelper.ParseDateTimeWithZone(elementText.ToString()); break; case "generator": channel.Generator = elementText.ToString(); break; case "docs": channel.Docs = elementText.ToString(); break; case "ttl": try { channel.TimeToLive = int.Parse(elementText.ToString()); } catch (Exception e) { exceptions.Add(e); } break; } break; case "image": switch (childElementName) { case "url": try { // OFxP, fix //image.Url = new Uri(elementText.ToString()); image.Url = new Uri(elementText.ToString(), true); } catch (Exception e) { exceptions.Add(e); } break; case "title": image.Title = elementText.ToString(); break; case "link": try { // OFxP, fix //image.Link = new Uri(elementText.ToString()); image.Link = new Uri(elementText.ToString(), true); } catch (Exception e) { exceptions.Add(e); } break; case "description": image.Description = elementText.ToString(); break; case "width": try { image.Width = Byte.Parse(elementText.ToString()); } catch (Exception e) { exceptions.Add(e); } break; case "height": try { image.Height = Byte.Parse(elementText.ToString()); } catch (Exception e) { exceptions.Add(e); } break; } break; case "textinput": switch (childElementName) { case "title": textInput.Title = elementText.ToString(); break; case "description": textInput.Description = elementText.ToString(); break; case "name": textInput.Name = elementText.ToString(); break; case "link": try { // OFxP, fix //textInput.Link = new Uri(elementText.ToString()); textInput.Link = new Uri(elementText.ToString(), true); } catch (Exception e) { exceptions.Add(e); } break; } break; case "skipdays": if (childElementName == "day") { channel.SkipDays |= Day.Parse(elementText.ToString()); } break; case "skiphours": if (childElementName == "hour") { channel.SkipHours |= Hour.Parse(elementText.ToString()); } break; } break; } case XmlNodeType.Text: elementText.Append(reader.Value); break; case XmlNodeType.CDATA: elementText.Append(reader.Value); break; } } }while (readData); return(rssElement); }
/// <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; bool pushElement = true; 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 { 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 (this.reader.IsEmptyElement) { break; } 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(); // 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(); 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; case "geo:lat": case "geo:long": case "geo:point": case "georss:point": case "georss:elev": case "georss:radius": if (this.item.GeoPoint == null) { this.item.GeoPoint = new RssGeoPoint(); } 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; case "geo:lat": try { this.item.GeoPoint.Lat = float.Parse(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; case "geo:long": try { this.item.GeoPoint.Lon = float.Parse(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; case "georss:point": try { string[] coords = this.elementText.ToString().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (coords.Length == 2) { this.item.GeoPoint.Lat = float.Parse(coords[0]); this.item.GeoPoint.Lon = float.Parse(coords[1]); } } catch (Exception e) { 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") { this.channel.SkipDays |= Day.Parse(this.elementText.ToString()); } break; case "skiphours": if (childElementName == "hour") { this.channel.SkipHours |= Hour.Parse(this.elementText.ToString()); } 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); }