Считывание RSS-чтения не удается из-за неверного XML - PullRequest
4 голосов
/ 16 октября 2011

Я написал фрагмент кода, который использует библиотеку System.ServiceModel.Syndication для разбора RSS-каналов.

Проблема в том, что для одного из моих каналов (который предоставляется Facebook) я получаю следующую строку в конце ответа, и библиотека синдикации не может проанализировать канал, потому что он говорит, что текст является недопустимым XML, и он говорит, что это из-за этой части:

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

Я уверен, что здесь есть кое-что, чего мне не хватает, потому что и фид, и библиотека синтаксического анализа созданы крупными компаниями (Facebook и Microsoft соответственно).

Кто-нибудь из вас может помочь? Или, в качестве альтернативы, лучший синтаксический анализатор, который не полагается на достоверность XML?

P.S. Вот мой RSS-канал:
http://www.facebook.com/feeds/page.php?id=202296766494181&format=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.

в System.Xml.XmlReader.ReadEndElement () ...

1 Ответ

8 голосов
/ 16 октября 2011

Кажется, что у SyndicationFeed проблема с доступом: элемент ограничения, используемый Facebook.См. Недавнюю ветку http://social.msdn.microsoft.com/Forums/ar/xmlandnetfx/thread/7045dc1c-1bd9-409a-9568-543e74f4578d

Майкл Сан (MSFT) написал: «Только что увидел пост Мартина! Очень полезно! Я также провел небольшое исследование по этой проблеме. Элемент взят из Bloglines, http://www.bloglines.com/index.html. Этозвучит как расширение, которое Facebook использует для своих каналов RSS 2.0, http://www.feedforall.com/access-namespace.htm. Из этой статьи кажется, что Rss20FeedFormatter - не единственный, который не поддерживает элементы.

Я согласен с Мартином использоватьXDocument (LINQ to XML) для анализа RSS-канала. Или, если вы создаете какое-то большое приложение с помощью C #, SDK Facebook C # также может быть полезен, 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, пропуская любой элемент после тега закрытия канала. (Имейте в виду, что приведенный ниже код не дает никаких гарантий, поскольку я считаю себя все еще начинающим разработчиком 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();
            }
        }
    }
}
...