C#反序列化XML文件报错:‘XML文档(1,2)存在错误’的排查
问题描述
尝试反序列化接口返回的XML响应,已使用Visual Studio的「选择性粘贴」功能生成对应实体类,仅将一个私有字段改为公共字段以在代码中访问(未修改代码片段内的内容)。但反序列化时出现如下错误:
错误信息
System.InvalidOperationException: 'There is an error in XML document (1, 2).' Inner Exception InvalidOperationException: <Envelope xmlns='http://schemas.xmlsoap.org/soap/envelope/'> was not expected.
实体类Envelope的起始代码
[System.SerializableAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://schemas.xmlsoap.org/soap/envelope/")] [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://schemas.xmlsoap.org/soap/envelope/", IsNullable = false)] public partial class Envelope { private object headerField; private EnvelopeBody bodyField; /// <remarks/> public object Header { get { return this.headerField; } set { this.headerField = value; } } /// <remarks/> public EnvelopeBody Body { get { return this.bodyField; } set { this.bodyField = value; } } }
待反序列化的XML起始内容
<SOAP:Envelope xmlns:SOAP='http://schemas.xmlsoap.org/soap/envelope/'> <SOAP:Header/> <SOAP:Body xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd' xmlns:urn='urn:oio:medarbejder:1.0.0' xmlns:urn1='urn:oio:sagdok:3.0.0'> <ns0:ListOutput xmlns:ns0='urn:oio:medarbejder:1.0.0'> <!-- 省略内部内容 --> </ns0:ListOutput> </SOAP:Body> </SOAP:Envelope>
曾尝试为[System.Xml.Serialization.XmlRootAttribute]添加ElementName属性,但仍出现相同错误。请问遗漏了什么?
解决方案
核心问题是实体类的Header和Body属性未指定SOAP命名空间,而XML中的<SOAP:Header>和<SOAP:Body>节点属于http://schemas.xmlsoap.org/soap/envelope/命名空间,序列化器无法匹配节点,导致报错。
步骤1:修正Envelope类的属性特性
给Header和Body属性添加XmlElement特性,明确指定命名空间:
[System.SerializableAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://schemas.xmlsoap.org/soap/envelope/")] [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://schemas.xmlsoap.org/soap/envelope/", IsNullable = false)] public partial class Envelope { private object headerField; private EnvelopeBody bodyField; /// <remarks/> [System.Xml.Serialization.XmlElementAttribute(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")] public object Header { get { return this.headerField; } set { this.headerField = value; } } /// <remarks/> [System.Xml.Serialization.XmlElementAttribute(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")] public EnvelopeBody Body { get { return this.bodyField; } set { this.bodyField = value; } } }
步骤2:验证EnvelopeBody及嵌套类的命名空间
确保EnvelopeBody类及其内部嵌套的所有实体类(比如ListOutput、LaesResultat等)的XML特性与XML中的对应节点命名空间完全匹配。例如ListOutput节点属于urn:oio:medarbejder:1.0.0命名空间,对应的类需要添加XmlRoot或XmlElement特性指定该命名空间。
步骤3:正确编写反序列化代码
使用XmlSerializer时,确保传入正确的类型,示例代码如下:
using (var reader = new StringReader(xmlContent)) { var serializer = new XmlSerializer(typeof(Envelope)); var envelope = (Envelope)serializer.Deserialize(reader); }
如果XML包含命名空间前缀映射,无需额外处理前缀,序列化器会自动识别命名空间的实际URI。
内容的提问来源于stack exchange,提问作者Kiesp
相关产品推荐
相关产品推荐

