由于无效的XML,聚合RSS阅读器失败

本文关键字:RSS 聚合 失败 XML 于无效 无效 | 更新日期: 2023-09-27 18:11:26

我编写了一段使用System.ServiceModel.Syndication库解析RSS提要的代码。

问题是,对于我的一个提要(这是由facebook提供的),我在响应和Syndication库的末尾得到以下行,无法解析提要,因为它说文本是无效的XML,它说这是因为这部分:

  ...
  </channel>
  <access:restriction relationship="deny" xmlns:access="http://www.bloglines.com/about/specs/fac-1.0" />
</rss>

我确信我在这里遗漏了一些东西,因为提要和解析库都来自大公司(分别是Facebook和Microsoft)。

你们有人能帮忙吗?或者选择一种不依赖于XML有效性的更好的解析器?

注:这是我的RSS订阅地址:
http://www.facebook.com/feeds/page.php?id=202296766494181&格式= rss20

下面是我解析提要响应的方法:
var stringReader = new StringReader(resp);
var xreader = XmlReader.Create(stringReader);
var xfeed = System.ServiceModel.Syndication.SyndicationFeed.Load(xreader);

和我得到的异常:

System.Xml.XmlException: 'Element' is an invalid XmlNodeType. Line 282, position 4.

由于无效的XML,聚合RSS阅读器失败

at System.Xml.XmlReader.ReadEndElement()

似乎SyndicationFeed与facebook使用的访问限制元素有问题。参见最近的帖子http://social.msdn.microsoft.com/Forums/ar/xmlandnetfx/thread/7045dc1c-1bd9-409a-9568-543e74f4578d

Michael Sun(微软)写道:"刚刚看到马丁的帖子!很有帮助!我也做了一些关于这个问题的研究。元素来自Bloglines, http://www.bloglines.com/index.html。这听起来像是facebook在RSS 2.0订阅中使用的扩展,http://www.feedforall.com/access-namespace.htm。从本文中可以看出,Rss20FeedFormatter并不是唯一不支持元素的。

我同意Martin使用XDocument (LINQ to XML)来解析RSS提要。或者,如果你正在通过c#构建一些大型应用程序,Facebook c# SDK也可以提供帮助,http://facebooksdk.codeplex.com/"

<我>编辑:

然而,似乎Atomfeed并没有遭受这个问题。最简单的解决方法将使用这个链接(http://www.facebook.com/feeds/page.php?id=202296766494181&format=atom10)。因此将格式参数从rss20更改为atom10

    HttpWebRequest req = WebRequest.Create(@"http://www.facebook.com/feeds/page.php?id=202296766494181&format=atom10") as HttpWebRequest;
        req.UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)";
        using (Stream responseStream = req.GetResponse().GetResponseStream())
        {
            using (XmlReader xr = XmlReader.Create(responseStream))
            {
                SyndicationFeed feed = SyndicationFeed.Load(xr);
            }
        }

另一种替代方法是编写一个继承的XMLTextReader覆盖ReadEndElement方法,方法是跳过通道关闭标记之后的任何Element。(请注意,下面的代码没有任何保证,因为我认为自己仍然是一个c#开发新手。如有错误请指正)

public class FaceBookReader : XmlTextReader
{
    public FaceBookReader(Stream stream)
        : base(stream) { }
    public FaceBookReader(String url)
        : base(url) { }
    public override void ReadEndElement()
    {
        string elementTag = this.LocalName.ToLower();
        base.ReadEndElement();
        // When we've read the channel End Tag, we're going to skip all tags
        // until we reach the a new Ending Tag which should be that of rss
        if (elementTag == "channel")
        {
            while (base.IsStartElement())
            {
                base.Skip();
            }
        }
    }
}