2008-09-17 25 views
9

¿Cuál es una forma sencilla de combinar feed y feed2? Quiero que los artículos de feed2 se agreguen a feed. También quiero evitar duplicados ya que feed podría tener elementos cuando una pregunta está etiquetada tanto con WPF como con Silverlight.Combinación de dos SyndicationFeeds

Uri feedUri = new Uri("http://stackoverflow.com/feeds/tag/silverlight"); 
XmlReader reader = XmlReader.Create(feedUri.AbsoluteUri); 
SyndicationFeed feed = SyndicationFeed.Load(reader);  

Uri feed2Uri = new Uri("http://stackoverflow.com/feeds/tag/wpf"); 
XmlReader reader2 = XmlReader.Create(feed2Uri.AbsoluteUri); 
SyndicationFeed feed2 = SyndicationFeed.Load(reader2); 

Respuesta

10

Puede usar LINQ para simplificar el código para unir dos listas (no olvide poner System.Linq en sus usos y si es necesario, haga referencia a System.Core en su proyecto) Aquí hay un Main que hace la unión y las imprime para consolar (con la limpieza adecuada del Reader).

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml; 
using System.ServiceModel.Syndication; 

namespace FeedUnion 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Uri feedUri = new Uri("http://stackoverflow.com/feeds/tag/silverlight"); 
      SyndicationFeed feed; 
      SyndicationFeed feed2; 
      using(XmlReader reader = XmlReader.Create(feedUri.AbsoluteUri)) 
      { 
       feed= SyndicationFeed.Load(reader); 
      } 
      Uri feed2Uri = new Uri("http://stackoverflow.com/feeds/tag/wpf"); 
      using (XmlReader reader2 = XmlReader.Create(feed2Uri.AbsoluteUri)) 
      { 
      feed2 = SyndicationFeed.Load(reader2); 
      } 
      SyndicationFeed feed3 = new SyndicationFeed(feed.Items.Union(feed2.Items)); 
      StringBuilder builder = new StringBuilder(); 
      using (XmlWriter writer = XmlWriter.Create(builder)) 
      { 
       feed3.SaveAsRss20(writer); 
       System.Console.Write(builder.ToString()); 
       System.Console.Read(); 
      } 
     } 
    } 
} 
+0

LINQ y UNION ... eso es genio. Esperaba que no iterar a través de los feeds y esto se ajusta a la ley. –

+0

¡Dulce! ¡Gracias! +1 – Charles

+0

Solución Genius. Gracias. –

0

Si es únicamente para stackoverflow, puede utilizar esto:
https://stackoverflow.com/feeds/tag/silverlight%20wpf
Este se hacer una unión de las dos marcas.

Para una solución más general, no sé. Probablemente tendrías que iterar manualmente los elementos de los dos feeds y unirlos. Puede comparar los < id> elementos de < entry> s para ver si son duplicados.

+0

creo que hará un AND en lugar de un OR. Creo que necesito unir los feeds. –

+0

Acabo de comprobar y es un OR –

+0

de acuerdo con esta publicación, está haciendo un AND. Creo que necesito esperar a la funcionalidad de UNION antes de poder usar las etiquetas RESTFUL uri. Mientras tanto, necesito repetirlo yo mismo y hacerlo manualmente. http://stackoverflow.com/questions/61590/stack-overflow-tag-filtering –

1

Bueno, una posibilidad es crear un nuevo feed de sindicación que sea un clon del primer feed, y luego simplemente iterar a través de cada publicación en el segundo, verificar el primero para su existencia, y agregarlo si no lo hace t existe.

Algo a lo largo de las líneas de:

SyndicationFeed newFeed = feed.clone; 
foreach(SyndicationItem item in feed2.items) 
{ 
    if (!newFeed.contains(item)) 
    newFeed.items.Add(item); 
} 

podría ser capaz de hacerlo. Parece que 'elementos' es una lista simple y numerable de elementos de sindicación, por lo que no hay razón por la que no pueda simplemente agregarlos.

+0

No creo que un simple Contiene() lo haga. Probablemente tendrá que comparar las identificaciones de entrada –

+0

Se recomienda que los elementos de elemento RSS tengan un elemento guid, pero no es obligatorio. Es probable que necesite determinar la inclusión cuando se combina al comparar primero GUID. Si el guid no está presente, compara los elementos del enlace. Puede querer comparar con el título para estar seguro también. – Oppositional

0

me he vuelto respuesta aceptada de hoy en una unidad de prueba sólo para explorar esta ligeramente:

[TestMethod] 
    public void ShouldCombineRssFeeds() 
    { 
     //reference: http://stackoverflow.com/questions/79197/combining-two-syndicationfeeds 

     SyndicationFeed feed; 
     SyndicationFeed feed2; 

     var feedUri = new Uri("http://stackoverflow.com/feeds/tag/silverlight"); 
     using(var reader = XmlReader.Create(feedUri.AbsoluteUri)) 
     { 
      feed = SyndicationFeed.Load(reader); 
     } 

     Assert.IsTrue(feed.Items.Count() > 0, "The expected feed items are not here."); 

     var feed2Uri = new Uri("http://stackoverflow.com/feeds/tag/wpf"); 
     using(var reader2 = XmlReader.Create(feed2Uri.AbsoluteUri)) 
     { 
      feed2 = SyndicationFeed.Load(reader2); 
     } 

     Assert.IsTrue(feed2.Items.Count() > 0, "The expected feed items are not here."); 

     var feedsCombined = new SyndicationFeed(feed.Items.Union(feed2.Items)); 

     Assert.IsTrue(
      feedsCombined.Items.Count() == feed.Items.Count() + feed2.Items.Count(), 
      "The expected number of combined feed items are not here."); 

     var builder = new StringBuilder(); 
     using(var writer = XmlWriter.Create(builder)) 
     { 
      feedsCombined.SaveAsRss20(writer); 
      writer.Flush(); 
      writer.Close(); 
     } 

     var xmlString = builder.ToString(); 

     Assert.IsTrue(new Func<bool>(
      () => 
      { 
       var test = false; 

       var xDoc = XDocument.Parse(xmlString); 
       var count = xDoc.Root.Element("channel").Elements("item").Count(); 
       test = (count == feedsCombined.Items.Count()); 

       return test; 
      } 
     ).Invoke(), "The expected number of RSS items are not here."); 
    } 
0
 //Executed and Tested :)    
     using (XmlReader reader = XmlReader.Create(strFeed)) 
     { 
      rssData = SyndicationFeed.Load(reader); 
      model.BlogFeed = rssData; ; 
     } 
     using (XmlReader reader = XmlReader.Create(strFeed1)) 
     { 
      rssData1 = SyndicationFeed.Load(reader); 
      model.BlogFeed = rssData1; 
     } 

     SyndicationFeed feed3 = new SyndicationFeed(rssData.Items.Union(rssData1.Items)); 
     model.BlogFeed = feed3;   
     return View(model); 
0

Esto funcionó bien para mí:

// create temporary List of SyndicationItem's 
List<SyndicationItem> tempItems = new List<SyndicationItem>(); 

// add all feed items to the list 
tempItems.AddRange(feed.Items); 
tempItems.AddRange(feed2.Items); 

// remove duplicates with Linq 'Distinct()'-method depending on yourattributes 

// add list without duplicates to 'feed2' 
feed2.Items = tempItems