1

我正在尝试反序列化一个 XML 文件,它工作正常,除了包含 HTML 标记的节点。下面是 XML 文件的一个片段:

<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 的算法,用于设计次优静态 H 2 /H无穷大输出反馈控制器

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

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

4

2 回答 2

4

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

该 XML 片段,正确转义将是

<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>
于 2013-10-10T05:33:00.793 回答
1

正如对上一个答案的评论所指出的那样 - 作为开发人员,我们并不总是可以在反序列化之前格式化 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方法将在该<title>字段中读取为未知字段。然后,您只需拉取内部 XML 的全部内容。

包含<sup> 也会跳闸Serializer_UnknownElement,但由于您没有条件,它会跳过它。

最终结果是Title_Custom现在将包含预期的完整 HTML 片段。

于 2019-05-20T20:04:30.843 回答