XML反序列化c#给出有效文档的错误

本文关键字:文档 错误 有效 反序列化 XML | 更新日期: 2023-09-27 18:07:31

我有很多具有相同结构的XML文件。他们中的许多工作正常,但对于一些XmlSerializer给了我一个错误,但当我把文档在xml验证器-它说文档是正确的。

反序列化代码:

var document = serializer.Deserialize(File.OpenRead(file));
错误:

System.InvalidOperationException: There is an error in XML document (504, 8). ---> System.Xml.XmlException: Unexpected node type Element. ReadElementString method can only be called on elements with simple or empty content. Line 504, position 8.
  at System.Xml.XmlReader.ReadElementString()
  at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderPatentdocument.Read33_Claimtext(Boolean isNullable, Boolean checkType)
  at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderPatentdocument.Read34_Claim(Boolean isNullable, Boolean checkType)
  at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderPatentdocument.Read35_Claims(Boolean isNullable, Boolean checkType)
  at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderPatentdocument.Read43_Patentdocument(Boolean isNullable, Boolean checkType)
  at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderPatentdocument.Read44_patentdocument()
  --- End of inner exception stack trace ---
  at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
  at System.Xml.Serialization.XmlSerializer.Deserialize(Stream stream)

给出错误的文档部分:

<text>12. Führungsschiene nach einem der Ansprüche 2 bis 11, dadurch gekennzeichnet, daß in den beiden Nutwänden (<b>11<i>a</i>, 11</b><i>a′)</i> einander gegenüberliegende Bohrungen (<b>14</b><i>a</i>, <b>14</b><i>a</i>′) vorgesehen sind, von denen die eine Bohrung (<b>14</b><i>a</i>′) durch das Einsatzteil (<b>15</b><i>a)</i> ver­schlossen ist.</text>

我想这是因为内联html标签在里面因为它抱怨这一行在的位置我标签

<b>11<i>a</i>, 11</b>

但是例如,根据XmlSerializer,这个xml是正确的,并且可以反序列化它:

<text>9. Führungsschiene nach Anspruch 8, dadurch gekennzeichnet, daß der Ansatz (<b>20</b>) die Zuführfläche (<b>25</b>) aufweist.</text>

所以我的问题是为什么xml验证器说文档是有效的,而XmlSerializer不能反序列化它?是否有可能在不更改文档的情况下找到解决方案?

XML反序列化c#给出有效文档的错误

当您指向内部HTML标记时,您是对的。您的XML无效,因为您在一个简单的(文本)元素中有标记。XmlSerializer无法理解并抛出错误。

如果您已经生成了XML文件,那么可以预先转义简单元素中的数据:

  • 与HTML编码
  • 或者将其封装在CDATA标签(<![CDATA[...]]>)

尝试序列化导致问题的实例。然后,可以将序列化的输出与试图反序列化的文件的内容进行比较。这两个XML字符串之间的差异将告诉您问题出在哪里。

下面是一个将类实例序列化为XML的快速函数:

    public static string Serialize<T>(T entity)
    {
        if (entity == null)
            return String.Empty;
        try
        {
            XmlSerializer XS = new XmlSerializer(typeof(T));
            System.IO.StringWriter SW = new System.IO.StringWriter();
            XS.Serialize(SW, entity);
            return SW.ToString();
        }
        catch (Exception e)
        {
            Logging.Log(Severity.Error, "Unable to serialize entity", e);
            return String.Empty;
        }
    }

如果你还没有尝试过,我建议你使用BeyondCompare软件来轻松查看两个文件之间的差异。

假设我们有以下类:

public class Foo
{
    //[XmlIgnore]
    public string Text { get; set; }
}

和以下格式的xml:

<Foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <text>12. Führungsschiene nach einem der Ansprüche 2 bis 11, dadurch gekennzeichnet, daß in den beiden Nutwänden (<b>11<i>a</i>, 11</b><i>a′)</i> einander gegenüberliegende Bohrungen (<b>14</b><i>a</i>, <b>14</b><i>a</i>′) vorgesehen sind, von denen die eine Bohrung (<b>14</b><i>a</i>′) durch das Einsatzteil (<b>15</b><i>a)</i> ver­schlossen ist.</text>
</Foo>

那么我们可以对数据进行如下反序列化。

var xs = new XmlSerializer(typeof(Foo));
xs.UnknownElement += Xs_UnknownElement;
Foo foo;
using (var fs = new FileStream("test.txt", FileMode.Open))
{
    foo = (Foo)xs.Deserialize(fs);
}

订阅XmlSerializerUnknownElement事件

在事件处理程序中手动设置我们的属性为data

private static void Xs_UnknownElement(object sender, XmlElementEventArgs e)
{
    var foo = (Foo)e.ObjectBeingDeserialized;
    foo.Text = e.Element.InnerXml;
}

请注意,属性名不应该匹配xml节点名(区分大小写)。只有在这种情况下才触发事件。如果名称匹配,则使用XmlIgnore属性。