Frage

Ich habe versucht, einige Routinen zu schreiben RSS und ATOM-Feeds mit den neuen Routinen in System.ServiceModel.Syndication zu lesen, aber leider aus den Rss20FeedFormatter Bomben auf über die Feeds Hälfte Ich versuche, mit folgenden Ausnahme:

An error was encountered when parsing a DateTime value in the XML.

Dies scheint auftreten, wenn der RSS-Feeds das Veröffentlichungsdatum in folgendem Format zum Ausdruck bringt:

  

Do 16 8. Oktober 14.23.26 -0700

Wenn der Feed das Datum als GMT veröffentlicht zum Ausdruck bringt, die Dinge in Ordnung:

  

Do 16 8. Oktober 21.23.26 GMT

Wenn es eine Möglichkeit gibt, um dieses mit XmlReaderSettings zu arbeiten, ich habe es nicht gefunden. Kann mir jemand helfen?

War es hilfreich?

Lösung

RSS 2.0 formatiert Syndication-Feeds der RFC 822 Datum-Zeitangabe nutzen, wenn die Serialisierung Elemente wie pubDate und lastbuilddate . Die RFC 822 Datum-Zeit-Spezifikation ist leider eine sehr ‚flexibel‘ Syntax zum Ausdrücken der Zeitzonenkomponente eines Datetime.

Zeitzone kann auf verschiedene Weise angezeigt werden. "UT" ist Universal Time (früher bekannt als "Greenwich Mean Time"); „GMT“ ist als Bezugnahme auf Universal Time erlaubt. Der Militär-Standard verwendet ein einzelnes Zeichen für jede Zone. "Z" ist Universal Time. „A“ zeigt eine Stunde früher, und „M“ gibt an 12 Stunden früher; „N“ ist eine Stunde später und „Y“ beträgt 12 Stunden später. Der Buchstabe „J“ wird nicht verwendet. Die anderen verbleibenden zwei Formen werden von ANSI-Standard X3.51-1975 genommen. One ermöglicht explizite Angabe der Menge von UT versetzt; der andere nutzt gemeinsame 3-Zeichenketten zur Anzeige Zeitzonen in Nordamerika.

Ich glaube, die Frage betrifft, wie die Zone Komponente des RFC 822 Datumszeitwert verarbeitet wird. Der Feed-Formatierer erscheint nicht als Datum-Zeiten Handhabung, die ein lokales Differential verwenden, um die Zeitzone anzuzeigen.

Als RFC 1123 die Spezifikation RFC 822 erstreckt, könnten Sie versuchen, die DateTimeFormatInfo.RFC1123Pattern ( "r") zu handhaben problamatic Datum-mal Umwandlung oder Ihren eigenen Parsing-Code für RFC 822 formatierten Daten schreiben. Eine andere Möglichkeit wäre eine dritte Partei Rahmen anstelle der System.ServiceModel.Syndication Namespace-Klassen zu verwenden sein.

Es scheint, gibt es einige bekannte Probleme mit Datum- Zeit-Analyse und die Rss20FeedFormatter, die in dem Prozess des von Microsoft gerichtet.

Andere Tipps

Auf der Grundlage der Problemumgehung in der Bug-Report Microsoft diesen habe ich speziell einen XmlReader für SyndicationFeeds zu lesen, die nicht-Standard-Termine haben.

Der folgende Code ist ein wenig anders als der Code in der Problemumgehung auf Microsofts Website. Es nimmt auch Oppositional Rat auf über das RFC-1123-Muster.

Statt einfach Aufruf XmlReader.Create () können Sie den XmlReader aus einem Stream erstellen müssen. Ich verwende die WebClient-Klasse, um diesen Strom zu bekommen:

WebClient client = new WebClient();
using (XmlReader reader = new SyndicationFeedXmlReader(client.OpenRead(feedUrl)))
{
    SyndicationFeed feed = SyndicationFeed.Load(reader);
    ....
    //do things with the feed
    ....
}

Im Folgenden finden Sie den Code für die SyndicationFeedXmlReader:

public class SyndicationFeedXmlReader : XmlTextReader
{
    readonly string[] Rss20DateTimeHints = { "pubDate" };
    readonly string[] Atom10DateTimeHints = { "updated", "published", "lastBuildDate" };
    private bool isRss2DateTime = false;
    private bool isAtomDateTime = false;

    public SyndicationFeedXmlReader(Stream stream) : base(stream) { }

    public override bool IsStartElement(string localname, string ns)
    {
        isRss2DateTime = false;
        isAtomDateTime = false;

        if (Rss20DateTimeHints.Contains(localname)) isRss2DateTime = true;
        if (Atom10DateTimeHints.Contains(localname)) isAtomDateTime = true;

        return base.IsStartElement(localname, ns);
    }

    public override string ReadString()
    {
        string dateVal = base.ReadString();

        try
        {
            if (isRss2DateTime)
            {
                MethodInfo objMethod = typeof(Rss20FeedFormatter).GetMethod("DateFromString", BindingFlags.NonPublic | BindingFlags.Static);
                Debug.Assert(objMethod != null);
                objMethod.Invoke(null, new object[] { dateVal, this });

            }
            if (isAtomDateTime)
            {
                MethodInfo objMethod = typeof(Atom10FeedFormatter).GetMethod("DateFromString", BindingFlags.NonPublic | BindingFlags.Instance);
                Debug.Assert(objMethod != null);
                objMethod.Invoke(new Atom10FeedFormatter(), new object[] { dateVal, this });
            }
        }
        catch (TargetInvocationException)
        {
            DateTimeFormatInfo dtfi = CultureInfo.CurrentCulture.DateTimeFormat;
            return DateTimeOffset.UtcNow.ToString(dtfi.RFC1123Pattern);
        }

        return dateVal;

    }

}

Auch dies ist fast genau von der Umgehung auf der Microsoft-Website in dem obigen Link gepostet kopiert. ... außer, dass diese funktioniert für mich, und die eine gepostete bei Microsoft nicht.

Hinweis : Ein bisschen Anpassung ist zu Beginn der Klasse in den beiden Feldern zu tun, die Sie benötigen. In Abhängigkeit von irgendwelchen Fremdfeldern Ihres Nicht-Standard-Feed hinzufügen kann, müssen Sie möglicherweise weitere Elemente in diese Arrays hinzuzufügen.

Interessant. Es wäre sieht aus wie die Datetime-Formatierung nicht einer von der, natürlich erwartet von dem Datetime-Parser ist. Nach einem Blick auf den Feed Klassen sieht es nicht wie Sie in Ihrer eigenen Formatierungskonvention für den Parser injizieren kann und sie nutzt wahrscheinlich ein bestimmtes Schema für das Gefühl zu validieren.

Unter Umständen können Sie ändern, wie der Datetime-Parser verhält sich durch die Modifizierung Kultur . Ich habe es nie zuvor getan, so kann ich nicht sicher sagen, dass es funktionieren würde.

Eine andere Lösung Nacht sein, zuerst das Futter verwandeln Sie lesen wollen. Wahrscheinlich nicht die beste, aber es könnten Sie, um das Problem zu bekommen.

Viel Glück.

Ein ähnliches Problem weiterhin besteht nach wie vor .NET 4.0 in und ich beschlossen, mit XDocument , anstatt direkt aufrufen SyndicationFeed zu arbeiten. Ich beschrieb die angewandte Methode (spezifisch für mein Projekt hier ). Kann nicht sagen, es ist die beste Lösung, aber es kann sicherlich ein „Backup-Plan“ für den Fall, SyndicationFeed in Betracht gezogen werden ausfällt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top