XML反序列化C#为有效文档提供错误

时间:2016-09-19 12:59:41

标签: c# .net xml xml-deserialization

我有很多具有相同结构的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标签,因为它在 i 标签的位置上抱怨这一行

<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无法反序列化它?是否可以在不更改文档的情况下获得解决方法?

3 个答案:

答案 0 :(得分:1)

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

如果您已生成XML文件,那么 可以预先删除简单元素中的数据

  • 使用HTML Encode
  • 或者将其封装在CDATA代码(mipmap

答案 1 :(得分:0)

尝试序列化导致问题的实例。然后,您可以将序列化的输出与您尝试反序列化的文件的内容进行比较。两个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轻松查看这两个文件之间的区别。

答案 2 :(得分:0)

假设我们有以下类:

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活动。

在事件处理程序中手动将我们的属性设置为数据。

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

请注意,属性名称不应与xml节点名称匹配(区分大小写)。仅在此情况下触发事件。如果名称匹配,请使用XmlIgnore属性。