RSS20FeedFormatter создает исключение при попытке прочитать некоторые форматы DateTime

В этой статье представлены сведения о том, System.Xml.XmlException когда используется SyndicationFeed.Load метод для считывания форматов даты из источника RSS.

Исходная версия продукта:   Microsoft .NET Framework
Исходный номер статьи базы знаний:   2020488

Симптомы

При использовании SyndicationFeed.Load метода чтения из источника RSS может появиться сообщение об ошибке, похожее на следующее:

System.Xml.XmlException: ошибка в строке 7, позиция 47. Произошла ошибка при синтаксическом анализе XML веб-канала. Для получения дополнительных сведений обратитесь к внутреннему исключению.
Строка не распознана как действительное значение DateTime.

Возможно, некоторые веб-каналы работают правильно, в то время как другие веб-каналы работают неправильно.

Причина

Эта проблема связана с форматом даты, используемым в веб-канале.SyndicationFeed.LoadМетод ожидает получения веб-каналов в стандартном формате. Ниже приведен пример стандартного формата:

Mon, 05 Oct 2009 08:00:06 GMT

Однако в некоторых веб-каналах используется другой формат.Например, некоторые веб-каналы могут использовать следующий формат:

Wed Oct 07 08:00:07 GMT 2009

Решение

Чтобы обойти эту проблему, создайте настраиваемое средство чтения XML, которое распознает различные форматы даты. Ниже приведен пример настраиваемого средства чтения XML:

XmlReader r = new MyXmlReader(url);
SyndicationFeed feed = SyndicationFeed.Load(r);

Rss20FeedFormatter rssFormatter = feed.GetRss20Formatter();
XmlTextWriter rssWriter = new XmlTextWriter("rss.xml", Encoding.UTF8);
rssWriter.Formatting = Formatting.Indented;
rssFormatter.WriteTo(rssWriter);
rssWriter.Close();

class MyXmlReader : XmlTextReader
{
    private bool readingDate = false;
    const string CustomUtcDateTimeFormat = "ddd MMM dd HH:mm:ss Z yyyy"; // Wed Oct 07 08:00:07 GMT 2009
    public MyXmlReader(Stream s) : base(s) { }
    public MyXmlReader(string inputUri) : base(inputUri) { }

    public override void ReadStartElement()
    {
        if (string.Equals(base.NamespaceURI, string.Empty, StringComparison.InvariantCultureIgnoreCase) &&
        (string.Equals(base.LocalName, "lastBuildDate", StringComparison.InvariantCultureIgnoreCase) ||
        string.Equals(base.LocalName, "pubDate", StringComparison.InvariantCultureIgnoreCase)))
        {
            readingDate = true;
        }
        base.ReadStartElement();
    }

    public override void ReadEndElement()
    {
        if (readingDate)
        {
            readingDate = false;
        }
        base.ReadEndElement();
    }

    public override string ReadString()
    {
        if (readingDate)
        {
            string dateString = base.ReadString();
            DateTime dt;
            if (!DateTime.TryParse(dateString, out dt))
                dt = DateTime.ParseExact(dateString, CustomUtcDateTimeFormat, CultureInfo.InvariantCulture);
            return dt.ToUniversalTime().ToString("R", CultureInfo.InvariantCulture);
        }
        else
        {
            return base.ReadString();
        }
    }
}