嘗試讀取某些 DateTime 格式時,RSS20FeedFormatter 會引發例外狀況

本文提供 System.Xml.XmlException 使用 SyndicationFeed.Load 方法從 RSS 來源讀取日期格式的相關資訊。

原始產品版本:   Microsoft .NET Framework
原始 KB 編號:   2020488

徵狀

當您使用 SyndicationFeed.Load 方法從 RSS 來源讀取時,可能會收到類似下列的錯誤訊息:

System.Xml.Xml例外狀況:第7行第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();
        }
    }
}