39 votes

Lecture d'éléments non standard dans un SyndicationItem avec SyndicationFeed

Avec .net 3.5, il existe un SyndicationFeed qui se charge dans un flux RSS et vous permettent d'exécuter des LINQ sur elle.

Voici un exemple de flux RSS que je suis de chargement:

<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>

Quand je boucle à travers les éléments, je peux récupérer le titre et le lien à travers les propriétés publiques de SyndicationItem.

Je n'arrive pas à comprendre comment obtenir les attributs de l'enceinte de la balise, ou les valeurs de la media tags. J'ai essayé d'utiliser

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

Aucune aide avec l'un de ces?

40voto

Ron Points 1315

Cela devrait vous donner une idée de la façon de procéder:

 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);
    }
}
 

19voto

jkade Points 81

Que vous récupériez le contenu non XML des éléments d'extension ou des éléments XElement, vous voudrez peut-être envisager d'utiliser une fonction d'assistance générique comme:

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

Selon que les éléments sont garantis ou que vous les placez dans une bibliothèque réutilisable, vous devrez peut-être ajouter une programmation défensive supplémentaire.

16voto

hitec Points 824

Voici comment j'ai réussi à récupérer le boîtier lien à partir d'un flux à l'aide de SyndicationFeed.

static void Main(string[] args)
{
    var feedUrl = "http://blog.stackoverflow.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);
    		}
    	}
    }
}

La sortie est comme suit:

Poste Titre: Podcast #50
Élément De Liens
Titre Du Lien:
URI: http://blog.stackoverflow.com/2009/04/podcast-50/
RelationshipType: autre
MediaType:
Longueur: 0
Titre Du Lien:
URI: http://itc.conversationsnetwork.org/audio/download/ITC.SO-Episode50-2009.04.21.mp3
RelationshipType: boîtier
MediaType: audio/mpeg
Longueur: 36580016

Vous pouvez identifier le boîtier lien à partir de son type de relation.

12voto

Oppositional Points 5966

Vous pouvez utiliser une combinaison de LINQ et XPathNavigator pour extraire les extensions de syndication d'un élément de flux (en fonction de l'URI de l'espace de noms de l'extension). Pour les pièces jointes d'élément, vous souhaiterez examiner la collection de liens d'élément pour les liens qui ont un type de boîtier RelationshipType.

Exemple:

 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;
            }
        }
    }
}
 

7voto

jr. Points 739

Votre manque de l'espace de noms. À l'aide de LINQPad et votre exemple de flux:

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 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>
    </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();

résultat: url="http://youtube.com/?v=y6_-cLWwEU0"

La construction de regarder, c'est: Élément(media + "le joueur") qui raconte Linq pour utiliser l'espace de noms représentés par des "médias" ainsi que le nom de l'élément 'joueur'.

Des dommages au cerveau doit être mise en de ma part, je pensais que vous étiez à l'aide de Linq. De toute façon, vous avez besoin de prendre l'espace de noms en considération.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X