结合两个 SyndicationFeed

Posted

技术标签:

【中文标题】结合两个 SyndicationFeed【英文标题】:Combining two SyndicationFeeds 【发布时间】:2010-09-09 21:38:33 【问题描述】:

结合 feedfeed2 的简单方法是什么?我希望将 feed2 中的项目添加到 feed。我还想避免重复,因为当问题同时被 WPF 和 Silverlight 标记时,feed 可能已经有项目。

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

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

【问题讨论】:

【参考方案1】:

您可以使用 LINQ 简化代码以加入两个列表(不要忘记将 System.Linq 放在您的 usings 中,如果需要,请在您的项目中参考 System.Core)这是一个 Main 执行联合并将它们打印到控制台(适当清理阅读器)。

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://***.com/feeds/tag/silverlight"); 
            SyndicationFeed feed;
            SyndicationFeed feed2;
            using(XmlReader reader = XmlReader.Create(feedUri.AbsoluteUri))
            
                feed= SyndicationFeed.Load(reader); 
            
            Uri feed2Uri = new Uri("http://***.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();
            
        
    

【讨论】:

LINQ 和 UNION...真是天才。我希望不要遍历提要,这符合要求。 很高兴你仍然发现它的用途:)【参考方案2】:

嗯,一种可能性是创建一个新的联合提要,它是第一个提要的克隆,然后简单地遍历第二个提要上的每个帖子,检查第一个是否存在,如果不存在则添加它存在。

类似的东西:

SyndicationFeed newFeed = feed.clone;
foreach(SyndicationItem item in feed2.items)

  if (!newFeed.contains(item))
    newFeed.items.Add(item);

也许可以做到。看起来“项目”是一个简单的可编号的联合项目列表,所以没有理由不能简单地添加它们。

【讨论】:

我不认为一个简单的 Contains() 会做到这一点。他可能需要比较条目 ID RSS 项目元素建议有一个 guid 元素,但这不是必需的。在组合时可能需要通过首先比较 guid 来确定包含。如果 guid 不存在,请比较链接元素。可能还想与标题进行比较以确保安全。【参考方案3】:

如果它只用于***,你可以使用这个:https://***.com/feeds/tag/silverlight%20wpf 这合并两个标签。

对于更通用的解决方案,我不知道。您可能必须手动迭代两个提要的元素并将它们连接在一起。您可以比较 元素,看看它们是否重复。

【讨论】:

我认为它会做 AND 而不是 OR。我想我需要合并提要。 我刚查了一下,结果是 OR 根据这篇文章,它正在执行 AND。我想我需要等待 UNION 功能才能使用 RESTFUL 标签 uri。与此同时,我需要自己迭代并手动完成。 ***.com/questions/61590/stack-overflow-tag-filtering【参考方案4】:

我将今天接受的答案变成了一个单元测试,只是为了稍微探索一下:

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

        SyndicationFeed feed;
        SyndicationFeed feed2;

        var feedUri = new Uri("http://***.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://***.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.");
    

【讨论】:

【参考方案5】:
        //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);

【讨论】:

【参考方案6】:

这对我来说很好用:

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

【讨论】:

以上是关于结合两个 SyndicationFeed的主要内容,如果未能解决你的问题,请参考以下文章

从C#SyndicationFeed中读取所有rss项

使用 SyndicationFeed 读取 SyndicationItem 中的非标准元素

结合两个 NSFetchedResultsController

在 NSPredicate 中结合两个条件

Redshift 结合两个查询

结合两个可观察序列