由于无效的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.
似乎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();
}
}
}
}