c# rss syndication-feed syndication-item

c# - Leer elementos no estándar en un SyndicationItem con SyndicationFeed



rss syndication-feed (5)

Puede usar una combinación de LINQ y XPathNavigator para extraer las extensiones de sindicación de un elemento de fuente (en función del URI de espacio de nombres de la extensión). Para los gabinetes de elementos, querrá examinar la colección de enlaces de elementos para los enlaces que tienen un RelationshipType de gabinete .

Ejemplo:

HttpWebRequest webRequest = WebRequest.Create("http://www.pwop.com/feed.aspx?show=dotnetrocks&filetype=master") as HttpWebRequest; using (Stream stream = webRequest.GetResponse().GetResponseStream()) { XmlReaderSettings settings = new XmlReaderSettings(); settings.IgnoreComments = true; settings.IgnoreWhitespace = true; using(XmlReader reader = XmlReader.Create(stream, settings)) { SyndicationFeed feed = SyndicationFeed.Load(reader); foreach(SyndicationItem item in feed.Items) { // Get values of syndication extension elements for a given namespace string extensionNamespaceUri = "http://www.itunes.com/dtds/podcast-1.0.dtd"; SyndicationElementExtension extension = item.ElementExtensions.Where<SyndicationElementExtension>(x => x.OuterNamespace == extensionNamespaceUri).FirstOrDefault(); XPathNavigator dataNavigator = new XPathDocument(extension.GetReader()).CreateNavigator(); XmlNamespaceManager resolver = new XmlNamespaceManager(dataNavigator.NameTable); resolver.AddNamespace("itunes", extensionNamespaceUri); XPathNavigator authorNavigator = dataNavigator.SelectSingleNode("itunes:author", resolver); XPathNavigator subtitleNavigator = dataNavigator.SelectSingleNode("itunes:subtitle", resolver); XPathNavigator summaryNavigator = dataNavigator.SelectSingleNode("itunes:summary", resolver); XPathNavigator durationNavigator = dataNavigator.SelectSingleNode("itunes:duration", resolver); string author = authorNavigator != null ? authorNavigator.Value : String.Empty; string subtitle = subtitleNavigator != null ? subtitleNavigator.Value : String.Empty; string summary = summaryNavigator != null ? summaryNavigator.Value : String.Empty; string duration = durationNavigator != null ? durationNavigator.Value : String.Empty; // Get attributes of <enclosure> element foreach (SyndicationLink enclosure in item.Links.Where<SyndicationLink>(x => x.RelationshipType == "enclosure")) { Uri url = enclosure.Uri; long length = enclosure.Length; string mediaType = enclosure.MediaType; } } } }

Con .net 3.5, hay una SyndicationFeed que se cargará en una fuente RSS y le permitirá ejecutar LINQ en ella.

Aquí hay un ejemplo del RSS que estoy cargando:

<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/"> <channel> <title>Title of RSS feed</title> <link>http://www.google.com</link> <description>Details about the feed</description> <pubDate>Mon, 24 Nov 08 21:44:21 -0500</pubDate> <language>en</language> <item> <title>Article 1</title> <description><![CDATA[How to use StackOverflow.com]]></description> <link>http://youtube.com/?v=y6_-cLWwEU0</link> <media:player url="http://youtube.com/?v=y6_-cLWwEU0" /> <media:thumbnail url="http://img.youtube.com/vi/y6_-cLWwEU0/default.jpg" width="120" height="90" /> <media:title>Jared on StackOverflow</media:title> <media:category label="Tags">tag1, tag2</media:category> <media:credit>Jared</media:credit> <enclosure url="http://youtube.com/v/y6_-cLWwEU0.swf" length="233" type="application/x-shockwave-flash"/> </item> </channel>

Cuando reviso los elementos, puedo recuperar el título y el enlace a través de las propiedades públicas de SyndicationItem.

Parece que no puedo entender cómo obtener los atributos de la etiqueta del gabinete o los valores de las etiquetas de los medios. Intenté usar

SyndicationItem.ElementExtensions.ReadElementExtensions<string>("player", "http://search.yahoo.com/mrss/")

¿Alguna ayuda con cualquiera de estos?


Te falta el espacio de nombres. Usando LINQPad y su feed de ejemplo:

string xml = @" <rss version=''2.0'' xmlns:media=''http://search.yahoo.com/mrss/''> <channel> <title>Title of RSS feed</title> <link>http://www.google.com</link> <description>Details about the feed</description> <pubDate>Mon, 24 Nov 08 21:44:21 -0500</pubDate> <language>en</language> <item> <title>Article 1</title> <description><![CDATA[How to use .com]]></description> <link>http://youtube.com/?v=y6_-cLWwEU0</link> <media:player url=''http://youtube.com/?v=y6_-cLWwEU0'' /> <media:thumbnail url=''http://img.youtube.com/vi/y6_-cLWwEU0/default.jpg'' width=''120'' height=''90'' /> <media:title>Jared on </media:title> <media:category label=''Tags''>tag1, tag2</media:category> <media:credit>Jared</media:credit> <enclosure url=''http://youtube.com/v/y6_-cLWwEU0.swf'' length=''233'' type=''application/x-shockwave-flash''/> </item> </channel> </rss> "; XElement rss = XElement.Parse( xml ); XNamespace media = "http://search.yahoo.com/mrss/"; var player = rss.Element( "channel" ).Element( "item" ).Element(media + "player").Attribute( "url" ); player.Dump();

resultado: url = "http://youtube.com/?v=y6_-cLWwEU0"

El constructo a mirar es: Elemento (medios + "jugador") que le dice a Linq que use el espacio de nombres representado por ''medios'', así como el nombre del elemento ''jugador''.

El daño cerebral debe ser de mi parte, pensé que estabas usando Linq. De todos modos, debes tener en cuenta el espacio de nombres.


Aquí es cómo logré recuperar el enlace del recinto de un feed usando SyndicationFeed.

static void Main(string[] args) { var feedUrl = "http://blog..com/index.php?feed=podcast"; using (var feedReader = XmlReader.Create(feedUrl)) { var feedContent = SyndicationFeed.Load(feedReader); if (null == feedContent) return; foreach (var item in feedContent.Items) { Debug.WriteLine("Item Title: " + item.Title.Text); Debug.WriteLine("Item Links"); foreach (var link in item.Links) { Debug.WriteLine("Link Title: " + link.Title); Debug.WriteLine("URI: " + link.Uri); Debug.WriteLine("RelationshipType: " + link.RelationshipType); Debug.WriteLine("MediaType: " + link.MediaType); Debug.WriteLine("Length: " + link.Length); } } } }

El resultado es el siguiente:

Título del artículo: Podcast # 50
Enlaces de artículos
Título del enlace:
URI: http://blog..com/2009/04/podcast-50/
RelationshipType: alternativo
Tipo de medio:
Longitud: 0
Título del enlace:
URI: http://itc.conversationsnetwork.org/audio/download/ITC.SO-Episode50-2009.04.21.mp3
RelationshipType: recinto
MediaType: audio / mpeg
Longitud: 36580016

Puede identificar el enlace del gabinete desde su tipo de relación.


Esto debería darte una idea sobre cómo hacerlo:

using System.Linq; using System.ServiceModel.Syndication; using System.Xml; using System.Xml.Linq;

SyndicationFeed feed = reader.Read(); foreach (var item in feed.Items) { foreach (SyndicationElementExtension extension in item.ElementExtensions) { XElement ele = extension.GetObject<XElement>(); Console.WriteLine(ele.Value); } }


Ya sea que esté recuperando el contenido no XML de elementos de extensión o elementos XElement, le recomendamos que considere utilizar una función auxiliar genérica como:

private static T GetExtensionElementValue<T>(SyndicationItem item, string extensionElementName) { return item.ElementExtensions.First(ee => ee.OuterName == extensionElementName).GetObject<T>(); }

Dependiendo de si los elementos están garantizados o si está colocando esto en una biblioteca reutilizable, es posible que deba agregar programación defensiva adicional.