private void ProcessHead(Opml opml, XmlNode headNode) { foreach (XmlNode node in headNode.ChildNodes) { string text = node.LocalName; text = string.IsInterned(text); if (text == "title") { opml.Title = node.InnerText; } else if (text == "dateCreated") { opml.DateCreated = DateTimeExt.Parse(node.InnerText); } else if (text == "dateModified") { opml.DateModified = DateTimeExt.Parse(node.InnerText); } else if (text == "ownerEmail") { opml.OwnerEmail = node.InnerText; } else if (text == "ownerName") { opml.OwnerName = node.InnerText; } } }
private static void ProcessFeedElements(Feed feed, XmlReader reader, string rssNamespaceUri, SyndicationFormat format, Hashtable optionalElements, ArrayList items, DateTime defaultItemDate) { bool matched = false; //indicates whether this is a known element bool nodeRead = false; //indicates whether the last node was read using XmlDocument.ReadNode() //string feedTitle = ""; //string feedDescription = ""; //string feedLink = ""; DateTime channelBuildDate = DateTime.MinValue; if ((format == SyndicationFormat.Rdf) || (format == SyndicationFormat.Rss)) { while ((nodeRead || reader.Read()) && reader.NodeType != XmlNodeType.EndElement) { object localname = reader.LocalName; object namespaceuri = reader.NamespaceURI; matched = false; nodeRead = false; if (reader.NodeType != XmlNodeType.Element) { continue; } if (reader.NamespaceURI.Equals(rssNamespaceUri) || reader.NamespaceURI.Equals(String.Empty)) { if (localname == nameRefs[(int)NameTableIndexes.title]) { if (!reader.IsEmptyElement) { feed.Title = ReadElementString(reader); } matched = true; } else if (localname == nameRefs[(int)NameTableIndexes.description]) { if (!reader.IsEmptyElement) { feed.Description = ReadElementString(reader); } matched = true; } else if (localname == nameRefs[(int)NameTableIndexes.link]) { if (!reader.IsEmptyElement) { feed.Link = ReadElementString(reader); } matched = true; } else if (localname == nameRefs[(int)NameTableIndexes.lastbuilddate]) { try { if (!reader.IsEmptyElement) { feed.LastBuildDate = DateTimeExt.Parse(ReadElementString(reader)); } } catch (FormatException fex) { System.Diagnostics.Debug.WriteLine(fex.ToString()); //_log.Warn("Error parsing date from channel {" + feedTitle + // "} from feed {" + (feedLink == null ? f.title : feedLink) + "}: ", fex); } finally { matched = true; } } else if (localname == nameRefs[(int)NameTableIndexes.items]) { reader.Skip(); matched = true; } else if ((localname == nameRefs[(int)NameTableIndexes.image]) && format == SyndicationFormat.Rdf) { reader.Skip(); matched = true; } else if (localname == nameRefs[(int)NameTableIndexes.item]) { if (!reader.IsEmptyElement) { FeedItem rssItem = MakeFeedItem(reader, defaultItemDate); if (rssItem != null) { rssItem.Parent = feed; //items.Add(rssItem); feed.Items.Add(rssItem); } } matched = true; } } else if (namespaceuri == nameRefs[(int)NameTableIndexes.ns_bandit_2003]) { if (localname == nameRefs[(int)NameTableIndexes.maxitemage]) { if (!reader.IsEmptyElement) { // get the old v1.2 value from cached feed // We used the TimeSpan.Parse() / maxItemAge.ToString() there, so we cannot simply take over the string. // Instead we convert to TimeSpan, then convert to valid xs:duration datatype to proceed correctly //f.maxitemage = XmlConvert.ToString(TimeSpan.Parse(ReadElementString(reader))); //f.maxitemage = ReadElementString(reader); } matched = true; } } if (!matched) { XmlQualifiedName qname = new XmlQualifiedName(reader.LocalName, reader.NamespaceURI); XmlNode optionalNode = optionalElementsDoc.ReadNode(reader); if (!optionalElements.Contains(qname)) { optionalElements.Add(qname, optionalNode); } nodeRead = true; } //if(!matched) } //while if (format == SyndicationFormat.Rdf) { reader.ReadEndElement(); //move to <image> or first <item>. do { object localname = reader.LocalName; nodeRead = false; if ((localname == nameRefs[(int)NameTableIndexes.image]) && reader.NamespaceURI.Equals(rssNamespaceUri)) { //RSS 1.0 can have <image> outside <channel> XmlNode optionalNode = optionalElementsDoc.ReadNode(reader); ((XmlElement)optionalNode).SetAttribute("xmlns", String.Empty); //change namespace decl to no namespace XmlQualifiedName qname = new XmlQualifiedName(optionalNode.LocalName, optionalNode.NamespaceURI); if (!optionalElements.Contains(qname)) { optionalElements.Add(qname, optionalNode); } nodeRead = true; } if ((localname == nameRefs[(int)NameTableIndexes.item]) && reader.NamespaceURI.Equals(rssNamespaceUri)) { if (!reader.IsEmptyElement) { FeedItem rssItem = MakeFeedItem(reader, defaultItemDate); if (rssItem != null) { items.Add(rssItem); } } } } while (nodeRead || reader.Read()); } // if(format == SyndicationFormat.Rdf) } else if (format == SyndicationFormat.Atom) { while ((nodeRead || reader.Read()) && reader.NodeType != XmlNodeType.EndElement) { object localname = reader.LocalName; object namespaceuri = reader.NamespaceURI; matched = false; nodeRead = false; if (reader.NodeType != XmlNodeType.Element) { continue; } if (reader.NamespaceURI.Equals(rssNamespaceUri) || reader.NamespaceURI.Equals(String.Empty)) { if (localname == nameRefs[(int)NameTableIndexes.title]) { if (!reader.IsEmptyElement) { feed.Title = ReadElementString(reader); } matched = true; } else if (localname == nameRefs[(int)NameTableIndexes.tagline]) { if (!reader.IsEmptyElement) { feed.Description = ReadElementString(reader); } matched = true; } else if (localname == nameRefs[(int)NameTableIndexes.link]) { string rel = reader.GetAttribute("rel"); string href = reader.GetAttribute("href"); if (feed.Link == String.Empty) { if ((rel != null) && (href != null) && rel.Equals("alternate")) { feed.Link = href; matched = true; } } } else if (localname == nameRefs[(int)NameTableIndexes.modified]) { try { if (!reader.IsEmptyElement) { feed.LastBuildDate = DateTimeExt.Parse(ReadElementString(reader)); } } catch (FormatException fex) { System.Diagnostics.Debug.WriteLine(fex.ToString()); //_log.Warn("Error parsing date from channel {" + feedTitle + // "} from feed {" + (feedLink == null ? f.title : feedLink) + "}: ", fex); } finally { matched = true; } } else if (localname == nameRefs[(int)NameTableIndexes.entry]) { if (!reader.IsEmptyElement) { FeedItem rssItem = MakeFeedItem(reader, defaultItemDate); if (rssItem != null) { items.Add(rssItem); } } matched = true; } } else if (namespaceuri == nameRefs[(int)NameTableIndexes.ns_bandit_2003]) { if (localname == nameRefs[(int)NameTableIndexes.maxitemage]) { if (!reader.IsEmptyElement) { // get the old v1.2 value from cached feed // We used the TimeSpan.Parse() / maxItemAge.ToString() there, so we cannot simply take over the string. // Instead we convert to TimeSpan, then convert to valid xs:duration datatype to proceed correctly TimeSpan maxItemAgeTS = TimeSpan.Parse(ReadElementString(reader)); if (maxItemAgeTS != TimeSpan.MaxValue) { //f.maxitemage = XmlConvert.ToString(maxItemAgeTS); } } matched = true; } } if (!matched) { XmlQualifiedName qname = new XmlQualifiedName(reader.LocalName, reader.NamespaceURI); XmlNode optionalNode = optionalElementsDoc.ReadNode(reader); if (!optionalElements.Contains(qname)) { optionalElements.Add(qname, optionalNode); } nodeRead = true; } //if(!matched) } //while } }
private static FeedItem MakeFeedItem(XmlReader reader, DateTime defaultItemDate) { string description = null; string id = null; string parentId = null; string link = null; string title = null; string subject = null; string author = null; Enclosure enclosure = null; bool dirtyFlag = false; //int commentCount = NewsItem.NoComments; int commentCount = 0; DateTime date = defaultItemDate; DateTime now = date; Hashtable optionalElements = new Hashtable(); //Flagged flagged = Flagged.None; ArrayList subjects = new ArrayList(); string itemNamespaceUri = reader.NamespaceURI; //the namespace URI of the RSS item bool nodeRead = false; //indicates whether the last node was read using XmlDocument.ReadNode() while ((nodeRead || reader.Read()) && reader.NodeType != XmlNodeType.EndElement) { nodeRead = false; object localname = reader.LocalName; object namespaceuri = reader.NamespaceURI; if (reader.NodeType != XmlNodeType.Element) { continue; } /* string nodeNamespaceUri = reader.NamespaceURI; * if (StringHelper.EmptyOrNull(nodeNamespaceUri)) * nodeNamespaceUri = itemNamespaceUri; */ // if in node has no namespace, assume in RSS namespace // save some string comparisons bool nodeNamespaceUriEqual2Item = reader.NamespaceURI.Equals(itemNamespaceUri); bool nodeNamespaceUriEqual2DC = (namespaceuri == nameRefs[(int)NameTableIndexes.ns_dc]); if ((description == null) || (localname == nameRefs[(int)NameTableIndexes.body]) || (localname == nameRefs[(int)NameTableIndexes.encoded])) { //prefer to replace rss:description/dc:description with content:encoded if ((namespaceuri == nameRefs[(int)NameTableIndexes.ns_xhtml]) && (localname == nameRefs[(int)NameTableIndexes.body])) { if (!reader.IsEmptyElement) { XmlElement elem = (XmlElement)optionalElementsDoc.ReadNode(reader); nodeRead = true; description = elem.InnerXml; elem = null; } continue; } else if ((namespaceuri == nameRefs[(int)NameTableIndexes.ns_content]) && (localname == nameRefs[(int)NameTableIndexes.encoded])) { if (!reader.IsEmptyElement) { description = ReadElementString(reader); } continue; } else if ((nodeNamespaceUriEqual2Item || nodeNamespaceUriEqual2DC) && (localname == nameRefs[(int)NameTableIndexes.description])) { if (!reader.IsEmptyElement) { description = ReadElementString(reader); } continue; } } if (localname == nameRefs[(int)NameTableIndexes.enclosure]) { enclosure = new Enclosure(); enclosure.Url = FeedParser.ReadAttribute(reader, "url"); enclosure.Type = FeedParser.ReadAttribute(reader, "type"); enclosure.Length = Convert.ToInt32(FeedParser.ReadAttribute(reader, "length")); } if (link != null && link.Trim().Length == 0) { link = null; // reset on empty elements } if ((link == null) || (localname == nameRefs[(int)NameTableIndexes.guid])) { //favor rss:guid over rss:link if (nodeNamespaceUriEqual2Item && (localname == nameRefs[(int)NameTableIndexes.guid])) { if ((reader["isPermaLink"] == null) || (StringHelper.AreEqualCaseInsensitive(reader["isPermaLink"], "true"))) { if (!reader.IsEmptyElement) { link = ReadElementString(reader); } } else if (StringHelper.AreEqualCaseInsensitive(reader["isPermaLink"], "false")) { if (!reader.IsEmptyElement) { id = ReadElementString(reader); } } continue; } else if (nodeNamespaceUriEqual2Item && (localname == nameRefs[(int)NameTableIndexes.link])) { if (!reader.IsEmptyElement) { link = ReadElementString(reader); } continue; } } if (title == null) { if (nodeNamespaceUriEqual2Item && (localname == nameRefs[(int)NameTableIndexes.title])) { if (!reader.IsEmptyElement) { title = ReadElementString(reader); } continue; } } if (localname == nameRefs[(int)NameTableIndexes.dirtyFlag]) { if (!reader.IsEmptyElement) { dirtyFlag = Boolean.Parse(ReadElementString(reader)); } continue; } if ((author == null) || (localname == nameRefs[(int)NameTableIndexes.creator])) { //prefer dc:creator to <author> if (nodeNamespaceUriEqual2DC && (localname == nameRefs[(int)NameTableIndexes.creator] || localname == nameRefs[(int)NameTableIndexes.author])) { if (!reader.IsEmptyElement) { author = ReadElementString(reader); } continue; } else if (nodeNamespaceUriEqual2Item && (localname == nameRefs[(int)NameTableIndexes.author])) { if (!reader.IsEmptyElement) { author = ReadElementString(reader); } continue; } } if ((parentId == null) && (localname == nameRefs[(int)NameTableIndexes.reference])) { if (namespaceuri == nameRefs[(int)NameTableIndexes.ns_annotate]) { parentId = reader.GetAttribute("resource", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); } continue; } if (nodeNamespaceUriEqual2DC && (localname == nameRefs[(int)NameTableIndexes.subject])) { if (!reader.IsEmptyElement) { subjects.Add(ReadElementString(reader)); } continue; } else if (nodeNamespaceUriEqual2Item && (localname == nameRefs[(int)NameTableIndexes.category])) { if (!reader.IsEmptyElement) { subjects.Add(ReadElementString(reader)); } continue; } if (commentCount == 0) { if ((localname == nameRefs[(int)NameTableIndexes.comments]) && (namespaceuri == nameRefs[(int)NameTableIndexes.ns_slash])) { try { if (!reader.IsEmptyElement) { commentCount = Int32.Parse(ReadElementString(reader)); } } catch (Exception) { /* DO NOTHING */ } continue; } } if (date == now) { try { if (nodeNamespaceUriEqual2Item && (localname == nameRefs[(int)NameTableIndexes.pubdate])) { if (!reader.IsEmptyElement) { date = DateTimeExt.Parse(ReadElementString(reader)); } continue; } else if (nodeNamespaceUriEqual2DC && (localname == nameRefs[(int)NameTableIndexes.date])) { if (!reader.IsEmptyElement) { date = DateTimeExt.ToDateTime(ReadElementString(reader)); } continue; } } catch (FormatException fe) { System.Diagnostics.Debug.WriteLine(fe.ToString()); /* date was improperly formated*/ //_log.Warn("Error parsing date from item {" + subject + // "} from feed {" + link + "}: " + fe.Message); continue; } } XmlQualifiedName qname = new XmlQualifiedName(reader.LocalName, reader.NamespaceURI); XmlNode optionalNode = optionalElementsDoc.ReadNode(reader); nodeRead = true; /* some elements occur multiple times in feeds, only the 1st is picked */ if (!optionalElements.Contains(qname)) { optionalElements.Add(qname, optionalNode); } } //while //HACK: Sometimes we get garbled items due to network issues, this ensures we don't send them to the UI if (link == null && id == null && title == null && date == now) { return(null); } /* create Subject if any */ for (int i = 0; i < subjects.Count; i++) { subject += (i > 0 ? " | " + subjects[i] : subjects[i]); } /* set value of id to link if no guid in XML stream */ id = (id == null ? link : id); FeedItem newsItem = new FeedItem(); //f, title, link, description, date, subject, ctype, optionalElements, id, parentId); newsItem.Title = title; newsItem.Id = id; newsItem.Link = link; newsItem.Description = description; newsItem.PubDate = date; newsItem.Enclosure = enclosure; newsItem.OptionalElements = optionalElements; newsItem.CommentCount = commentCount; newsItem.Author = author; newsItem.DirtyFlag = dirtyFlag; return(newsItem); }