【问题标题】:Deserializing XML with HTML tags使用 HTML 标签反序列化 XML
【发布时间】:2019-05-21 04:04:30
【问题描述】:

我正在尝试反序列化一个 XML 文件,除了包含 HTML 标记的节点外,它工作正常。这是 XML 文件中的一个 sn-p:

<article mdate="2011-12-29" key="tr/trier/MI99-02" publtype="informal publication">
    <author>Friedemann Leibfritz</author>
    <title>A LMI-Based Algorithm for Designing Suboptimal Static H<sub>2</sub>/H<sub>infinity</sub> Output Feedback Controllers</title>
    <journal>Universit&auml;t Trier, Mathematik/Informatik, Forschungsbericht</journal>
    <volume>99-02</volume>
    <year>1999</year>
</article>

然后,我收到错误:

{"Unexpected node type Element. ReadElementString method can only be called on elements with simple or empty content. Line 1148, position 64."}

错误发生在:

一种基于LMI的算法设计次优静态H2/Hinfinity输出反馈控制器

HTML 标签 sub 和 /sub 存在的地方。

有没有办法将标题节点作为一个整体反序列化,而忽略 HTML 标签?以下是我的部分代码:

XmlReaderSettings readerSettings = new XmlReaderSettings
{
   DtdProcessing = DtdProcessing.Parse,
   XmlResolver = new LocalXhtmlXmlResolver()
};

XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "dblp";
xRoot.IsNullable = true;
XmlSerializer deserializer;
XmlReader textReader;

deserializer = new XmlSerializer(typeof(List<Entity.Article>), xRoot);
textReader = XmlReader.Create(xmlPath, readerSettings);
List<Entity.Article> articleList;
articleList = (List<Entity.Article>)deserializer.Deserialize(textReader);
textReader.Close();

任何帮助将不胜感激 - 谢谢!

【问题讨论】:

    标签: c# xml serialization


    【解决方案1】:

    您的 XML 未正确转义。解析器无法知道这些标签不是 XML 文档的一部分,当它们被这样处理时,您的 XML 是无效的,因为一个元素嵌套在另一个元素的值中。

    正确转义的 XML sn-p 将是

    <article mdate="2011-12-29" key="tr/trier/MI99-02" publtype="informal publication">
        <author>Friedemann Leibfritz</author>
        <title>A LMI-Based Algorithm for Designing Suboptimal Static H&lt;sub&gt;2&lt;/sub&gt;/H&lt;sub&gt;infinity&lt;/sub&gt; Output Feedback Controllers</title>
        <journal>Universit&auml;t Trier, Mathematik/Informatik, Forschungsbericht</journal>
        <volume>99-02</volume>
        <year>1999</year>
    </article>
    

    【讨论】:

    • 您好,感谢您的回复!要求不修改 XML 文件。此外,XML 文件大约有 1.2GB 大,可能还有其他尚未发现的 HTML 标记(例如,)。有什么办法可以跳过这些元素吗?
    • 没有当前有一个有效的 XML 文件,你不能跳过你不喜欢的部分——你的要求类似于写一个带有随机“{”的 C# 应用程序散布在整个源代码中,并要求编译器跳过不应该存在的那些。你可以做的是处理文本文件,尝试用正确转义的标签替换已知的坏 HTML 标签,但这本身很危险 - 你确定没有文件中的 XML &lt;sub&gt; 元素? &lt;strike&gt; 呢? &lt;head&gt;?这里真正的问题是需要正确生成 XML。
    【解决方案2】:

    正如上一个答案的 cmets 所指出的那样——作为开发人员,我们并不总是能够在反序列化之前对 XML 进行格式化。在我看来,有一个更优雅的解决方案可以满足最初的问题。

    序列化器

    public static T ParseXml<T>(this string @this) where T : class
    {
        var serializer = new XmlSerializer(typeof(T));
        serializer.UnknownElement += Serializer_UnknownElement;
        return serializer.Deserialize(new StringReader(@this)) as T;            
    }
    

    处理有问题的字段

    private static void Serializer_UnknownElement(object sender, XmlElementEventArgs e)
    {
        if (e.ObjectBeingDeserialized is Article article)
        {
            if (e.Element.Name == "title")
            {
                article.Title_Custom = e.Element.InnerXml;
                return;
            }
        }
    }
    

    对文章类的修改

    public class Article{
      // include your other fields that are not problematic
      public string Title_Custom { get; set; }
    }
    

    用法

    var myArticles = articlesXmlString.Parse<List<Article>>();
    Console.Out(myArticles[0].Title_Custom); // "A LMI-Based Algorithm for Designing Suboptimal Static H<sub>2</sub>/H<sub>infinity</sub> Output Feedback Controllers"
    

    因为现在属性的名称是Title_Custom,它自然会作为反序列化过程的一部分被跳过。然后Serializer_UnknownElement 方法将在&lt;title&gt; 字段中读取为未知字段。然后,您只需拉取内部 XML 的全部内容。

    包含&lt;sup&gt; 绊倒Serializer_UnknownElement,但由于您没有条件,它会跳过它。

    最终结果是Title_Custom 现在将按预期包含完整的 HTML sn-p。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-07
      • 1970-01-01
      • 2022-11-10
      • 2015-05-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多