2012-01-17 14 views
8

Estoy intentando analizar alimentaciones Rss2, Atom utilizando objetos SyndicationFeed. Pero me estoy XmlExceptions al analizar el campo DateTime como pubDateExcepciones con el análisis de DateTime en la fuente RSS use SyndicationFeed en C#

2012-01-17 08:01:06

public static List<SyndicationItem> getRssData(string url) 
{ 
    List<SyndicationItem> list = new List<SyndicationItem>(); 

    WebClient client = new WebClient(); 
    try 
    { 
     SyndicationFeed feed = SyndicationFeed.Load(XmlReader.Create(url)); 
     list = (from item in feed.Items select item).ToList(); 
    } 
    catch (Exception e) 
    { 
     throw e; 
    } 

    return list; 
} 

el enlace URL http://news.163.com/special/00011K6L/rss_newstop.xml

<item id="2"> 
    <title>...</title> 
    <link>...</link> 
    <description>......</description> 
    <pubDate>2012-01-17 12:09:29</pubDate><-----Exception 
</item> 

¿Hay una mejor manera de ¿lograr esto? Por favor ayuda. Gracias.

+3

Solo por curiosidad, ¿por qué estás usando una expresión de consulta LINQ para obtener la lista? Es equivalente a 'list = feed.Items.ToList();'. No es parte del problema, pero aun así ... (Del mismo modo, por favor no capte excepciones solo para tirarlas de nuevo, y si * desea * atrapar y volver a lanzar, simplemente use 'throw;' en lugar de 'throw e ; '.) –

Respuesta

3

Básicamente, ese canal RSS no es válido. Si nos fijamos en la RSS 2.0 specification se establece que:

Todas fecha-hora en RSS se ajustan a la fecha y la hora Especificación de la RFC 822, con la excepción de que el año se puede expresar con dos caracteres o cuatro caracteres (cuatro privilegiado).

La cadena "2012-01-17 12:09:29" no cumple con "Date and Time" part of RFC 822. Debe ser "17 01 2012 12:09:29" o algo similar.

14

Hay una solución RSS20FeedFormatter throws exception trying to read some DateTime formats.

Para solucionar este problema, cree un lector de XML personalizado que reconozca los diferentes formatos de fecha. El siguiente es un ejemplo de un lector de 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(); 

clase ..y utilizado en el código anterior:

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