代码之家  ›  专栏  ›  技术社区  ›  Cheeso

当RSS文档包含嵌入在元素中的<script>块时,System.ServiceModel.Syndication.SyndicationFeed将引发

  •  1
  • Cheeso  · 技术社区  · 14 年前

    代码:

    使用(xmlreader xmlr=xmlreader.create(new stringreader(allxml)))
    {
    var items=来自syndicationfeed.load(xmlr).items中的项
    选择项目;
    }
    < /代码> 
    
    

    例外情况:

    exception:system.xml.xml exception:unexpected node type element.
    只能对内容为简单或空的元素调用ReadElementString方法。第11行,位置25。
    在system.xml.xmlReader.readElementString()处
    在System.ServiceModel.Syndication.rss20 FeedFormatter.readXML(XmlReader Reader,SyndicationFeed结果)
    在System.ServiceModel.Syndication.rss20 FeedFormatter.ReadFeed(XmlReader Reader)上
    在System.ServiceModel.Syndication.rss20 FeedFormatter.ReadFrom(XmlReader Reader)上
    在System.ServiceModel.Syndication.SyndicationFeed.Load[TSyndicationFeed](XmlReader阅读器)
    在System.ServiceModel.Syndication.SyndicationFeed.Load上(XmlReader Reader)
    位于c:\dev\dotnet\readrss.cs:line 90中的ionic.toolsandtests.readrss.run()。
    < /代码> 
    
    

    XML内容:

    <?xml version=“1.0”encoding=“utf-8”?gt;
    &?XML样式表type=“text/xsl”href=“https://www.ibm.com/developerWorks/mydeveloperWorks/blogs/roller-ui/styles/rss.xsl”media=“screen”?><rss版本=“2.0”
    xmlns:dc=“http://purl.org/dc/elements/1.1/”
    xmlns:atom=“http://www.w3.org/2005/atom”>
    通道& GT;
    <title>软件架构、软件工程和文艺复兴爵士乐</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“//gt;
    <description>软件架构、软件工程和Renaission Jazz</description>
    <language>en-us</language>
    <copyright>copyright<script type='text/javascript'>document.write(blogsdate.date.localize(1273534889181));</script></copyright>
    <lastbuilddate>2010年5月10日周一19:41:29-0400</lastbuilddate>
    < /代码> 
    
    

    如您所见,在第11行的位置25处,在<copyright>元素内有一个脚本块。

    其他人们报告了其他XML文档的类似错误

    我解决这个问题的方法是先做一个streamreader.readtoend,然后再做regex.replace,结果是在 将修改后的字符串传递给xmlReader.create()。感觉像个黑客。


    1. 有人有更好的方法吗?我不喜欢这样,因为我必须把125K的字符串读入内存。

    2. 是否有效的RSS包含这样的“复杂内容”——元素中的脚本块?

    例外情况:

    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
    

    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>
    

    如您所见,在第11行的位置25处,在<copyright>元素。

    其他人们报告了类似的错误其他XML文档。

    我解决这个问题的方法是先做一个streamreader.readtoend,然后再做regex.replace,结果是在 将修改后的字符串传递给xmlReader.create()。感觉像个黑客。


    1. 有人有更好的方法吗?我不喜欢这样,因为我必须把125K的字符串读入内存。

    2. 是否有效的RSS包含这样的“复杂内容”——元素中的脚本块?

    1 回复  |  直到 14 年前
        1
  •  0
  •   David Anderson    14 年前

    您可以子类 XmlTextReader 超驰 ReadElementString 在读取时跳过或修改有问题的元素。仍然感觉像一个黑客,但至少避免预处理与regex。

    下面是一个完成工作的简单实现:

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

    然后,您的示例代码如下所示:

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