Combining two SyndicationFeeds
Asked Answered
W

6

10

What's a simple way to combine feed and feed2? I want the items from feed2 to be added to feed. Also I want to avoid duplicates as feed might already have items when a question is tagged with both WPF and Silverlight.

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);
Whitehorse answered 17/9, 2008 at 2:13 Comment(0)
V
11

You can use LINQ to simplify the code to join two lists (don't forget to put System.Linq in your usings and if necessary reference System.Core in your project) Here's a Main that does the union and prints them to console (with proper cleanup of the 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();
            }
        }
    }
}
Vickivickie answered 17/9, 2008 at 18:49 Comment(2)
LINQ and UNION... that's genius. I was hoping that to not iterate through the feeds and this fits the bill.Whitehorse
Glad you're still finding a use for this :)Vickivickie
R
1

Well, one possibility is to create a new syndication feed that is a clone of the first feed, and then simply iterate through each post on the second one, check the first for its existence, and add it if it doesn't exist.

Something along the lines of:

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

might be able to do it. It looks like 'items' is a simple enumberable list of syndication items, so theres not reason you can't simply add them.

Readiness answered 17/9, 2008 at 2:41 Comment(2)
I don't think a simple Contains() will do it. He'll probably have to compare entry IDsDiligent
RSS item elements are recommended to have a guid element, but it is not required. Will liklely need to determine inclusion when combining by first comparing guid. If guid not present, compare the link elements. May want to compare against title to be safe as well.Fortunato
D
0

If it's solely for stackoverflow, you can use this :
https://stackoverflow.com/feeds/tag/silverlight%20wpf
This will do an union of the two tags.

For a more general solution, I don't know. You'd probably have to manually iterate the elements of the two feeds and join them together. You can compare the <id> elements of <entry>s to see if they are duplicates.

Diligent answered 17/9, 2008 at 2:40 Comment(3)
I think that it will do an AND instead of an OR. I think I need to union the feeds.Whitehorse
I just checked and it's an ORDiligent
according to this post, it's doing an AND. I think I need to wait for the UNION functionality before I can use the RESTFUL tags uri. In the meantime I need iterate through it myself and do it manually. stackoverflow.com/questions/61590/stack-overflow-tag-filteringWhitehorse
M
0

I've turned today's accepted answer into a unit test just to explore this slightly:

    [TestMethod]
    public void ShouldCombineRssFeeds()
    {
        //reference: https://mcmap.net/q/1084463/-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.");
    }
Marcin answered 18/1, 2012 at 19:38 Comment(0)
B
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);
Bernardina answered 29/7, 2013 at 6:39 Comment(0)
C
0

This worked fine for me:

// 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
Coster answered 6/2, 2016 at 9:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.