2 votes

System.ServiceModel.Syndication.SyndicationFeed se lance lorsque le document RSS comprend un bloc <script> intégré dans un élément.

Le code :

using (XmlReader xmlr = XmlReader.Create(new StringReader(allXml)))
{
    var items = from item in SyndicationFeed.Load(xmlr).Items
        select item;
}

L'exception :

Exception: System.Xml.XmlException: Unexpected node type Element. 
   ReadElementString method can only be called on elements with simple or empty content. Line 11, position 25.
   at System.Xml.XmlReader.ReadElementString()
   at System.ServiceModel.Syndication.Rss20FeedFormatter.ReadXml(XmlReader reader, SyndicationFeed result)
   at System.ServiceModel.Syndication.Rss20FeedFormatter.ReadFeed(XmlReader reader)
   at System.ServiceModel.Syndication.Rss20FeedFormatter.ReadFrom(XmlReader reader)
   at System.ServiceModel.Syndication.SyndicationFeed.Load[TSyndicationFeed](XmlReader reader)
   at System.ServiceModel.Syndication.SyndicationFeed.Load(XmlReader reader)
   at Ionic.ToolsAndTests.ReadRss.Run() in c:\dev\dotnet\ReadRss.cs:line 90

Le contenu XML :

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="https://www.ibm.com/developerworks/mydeveloperworks/blogs/roller-ui/styles/rss.xsl" media="screen"?><rss version="2.0" 
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:atom="http://www.w3.org/2005/Atom" >
<channel>
  <title>Software architecture, software engineering, and Renaissance Jazz</title>
  <link>https://www.ibm.com/developerworks/mydeveloperworks/blogs/gradybooch</link>
  <atom:link rel="self" type="application/rss+xml" href="https://www.ibm.com/developerworks/mydeveloperworks/blogs/gradybooch/feed/entries/rss?lang=en" />
  <description>Software architecture, software engineering, and Renaissance Jazz</description>
  <language>en-us</language>
  <copyright>Copyright <script type='text/javascript'> document.write(blogsDate.date.localize (1273534889181));</script></copyright>
  <lastBuildDate>Mon, 10 May 2010 19:41:29 -0400</lastBuildDate>

Comme vous pouvez le voir, à la ligne 11, à la position 25, il y a un bloc script à l'intérieur de la balise <copyright> élément.

Autre des personnes ont signalé des erreurs similaires avec d'autres documents XML.

La façon dont j'ai contourné ce problème était de faire un StreamReader.ReadToEnd, puis de faire Regex.Replace sur le résultat de celui-ci pour enlever le bloc script, avant de passer la chaîne modifiée à XmlR. de passer la chaîne modifiée à XmlReader.Create(). J'ai l'impression d'être un hacker.


  1. Quelqu'un a-t-il une meilleure approche ? Je n'aime pas ça parce que je dois lire une chaîne de 125k en mémoire.

  2. Est-ce que c'est un rss valide d'inclure un "contenu complexe" comme ça - un bloc script à l'intérieur d'un élément ?

1voto

Dave76 Points 1181

Vous pouvez sous-classer XmlTextReader et de passer outre ReadElementString pour sauter ou modifier l'élément incriminé lors de sa lecture. Cela ressemble toujours à un piratage mais évite au moins le prétraitement par regex.

Voici une mise en œuvre simple qui permet de faire le travail :

class BrokenFeedXmlReader : XmlTextReader 
{
    // Additional XmlTextReader constructors can be added in 
    // similar fashion as needed
    public BrokenFeedXmlReader(TextReader input)
        : base(input)
    {
    }

    public override string ReadElementString()
    {
        if ("copyright" == Name)
        {
            base.Skip();
            return String.Empty; 
        }

        return base.ReadElementString();
    }            
}

Votre exemple de code ressemblerait alors à quelque chose comme ceci :

using (XmlReader xmlr = new BrokenFeedXmlReader(new StringReader(allXml)))
{
    var items = from item in SyndicationFeed.Load(xmlr).Items
                select item;
}

0voto

Cheeso Points 87022

Non, personne n'a une meilleure approche.

Non, ça n'a pas l'air d'être des RSS valides. C'est au moins des mauvaises manières.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X