RSS20FeedFormatter produce una excepción al intentar leer algunos formatos DateTime

En este artículo se proporciona información sobre cuándo se usa el método para System.Xml.XmlException SyndicationFeed.Load leer formatos de fecha desde un origen RSS.

Versión del producto original:   Microsoft .NET Framework
Número KB original:   2020488

Síntomas

Cuando usa el método para leer desde un origen RSS, puede recibir un SyndicationFeed.Load mensaje de error similar al siguiente:

System.Xml. XmlException: error en la línea 7 posición 47. Se encontró un error al analizar el XML de la fuente. Para obtener más información, consulte la excepción interna.
String no se reconoció como un DateTime válido.

Algunas fuentes funcionan correctamente mientras que otras fuentes funcionan incorrectamente.

Causa

Este problema se produce debido al formato de fecha que se usa en la fuente. El método espera recibir fuentes en SyndicationFeed.Load formato estándar. A continuación se muestra un ejemplo de formato estándar:

Mon, 05 Oct 2009 08:00:06 GMT

Sin embargo, algunas fuentes usan un formato diferente. Por ejemplo, algunas fuentes pueden usar el siguiente formato:

Wed Oct 07 08:00:07 GMT 2009

Solución

Para solucionar este problema, cree un lector XML personalizado que reconozca diferentes formatos de fecha. A continuación se muestra un ejemplo de un lector XML personalizado:

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();
        }
    }
}