由于命名空间而无法反序列化 xml
Posted
技术标签:
【中文标题】由于命名空间而无法反序列化 xml【英文标题】:Failed deserializing xml due to namespaces 【发布时间】:2021-07-02 01:09:07 【问题描述】:我有以下要反序列化为 c# 类的 xml:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://www.s1.com/info/" xmlns:types="http://www.s1.com/info/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<tns:SessionInfo>
<SessionId xsi:type="xsd:string">string</SessionId>
</tns:SessionInfo>
</soap:Header>
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<tns:LoginResponse>
<Result xsi:type="xsd:boolean">boolean</Result>
</tns:LoginResponse>
</soap:Body>
</soap:Envelope>
我正在使用以下类来反序列化 xml:
public class SessionId
[XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public string Type get; set;
[XmlText]
public string Text get; set;
[XmlRoot(ElementName = "SessionInfo", Namespace = "http://www.s1.com/info/")]
public class SessionInfo
[XmlElement(ElementName = "SessionId")]
public SessionId SessionId get; set;
[XmlAttribute(AttributeName = "id", Namespace = "")]
public string Id get; set;
[XmlText]
public string Text get; set;
[XmlRoot(ElementName = "Header", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Header
[XmlElement(ElementName = "SessionInfo", Namespace = "http://www.s1.com/info/")]
public SessionInfo SessionInfo get; set;
[XmlRoot(ElementName = "Result", Namespace = "")]
public class Result
[XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public string Type get; set;
[XmlText]
public string Text get; set;
[XmlRoot(ElementName = "LoginResponse", Namespace = "http://www.s1.com/info/")]
public class LoginResponse
[XmlElement(ElementName = "Result")]
public Result Result get; set;
[XmlRoot(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Body
[XmlElement(ElementName = "LoginResponse", Namespace = "http://www.s1.com/info/")]
public LoginResponse LoginResponse get; set;
[XmlAttribute(AttributeName = "encodingStyle", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public string EncodingStyle get; set;
[XmlText]
public string Text get; set;
[XmlRoot(ElementName = "Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope
[XmlElement(ElementName = "Header", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public Header Header get; set;
[XmlElement(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public Body Body get; set;
[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xsi get; set;
[XmlAttribute(AttributeName = "xsd", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xsd get; set;
[XmlAttribute(AttributeName = "soapenc", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Soapenc get; set;
[XmlAttribute(AttributeName = "tns", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Tns get; set;
[XmlAttribute(AttributeName = "types", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Types get; set;
[XmlAttribute(AttributeName = "soap", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Soap get; set;
[XmlText]
public string Text get; set;
问题是 SessionId 元素没有被反序列化,我假设是由于命名空间不匹配。我尝试使用空字符串作为命名空间,但这也不起作用,因为它在反序列化过程中无法被识别。
非常感谢您对问题的任何见解。谢谢!
【问题讨论】:
添加命名空间:[XmlElement(ElementName = "SessionId", Namespace = "s1.com/info/")] @jdweng 我试过了,但好像不行。 将 SessionId 设为字符串:[XmlElement(ElementName = "SessionId", Namespace = "")] public string SessionId get;放; 【参考方案1】:首先,SessionId
有错误的命名空间。它从父级继承,您需要通过将其设置为空字符串来明确指定它没有。
其次,xsi:type
有特殊含义,你不应该尝试反序列化它。它用于指示元素的内容类型 - 在本例中为 string
- 并将由序列化程序使用。这意味着这是许多可接受的类型之一。最简单的定义方法是使用object
。
将它们放在一起,这应该可以工作:
[XmlElement(ElementName = "SessionId", Namespace = "")]
public object SessionId get; set;
SessionId
应该包含一个 string
对象,其值为 string
。
我还要注意其他一些小事:
不应将所有命名空间绑定(例如Xsd
)指定为模型的一部分。这比此模型低级别,将由序列化程序处理。
你只需要在根目录下XmlRoot
你不需要XmlText
没有任何文本的属性
您需要对上面进行类似的更改以反序列化Result
ElementName
和 AttributeName
将默认为属性的名称,因此如果您需要,则不必指定这些
考虑到这一点,这个模型应该可以工作:
public class SessionInfo
[XmlElement(Namespace = "")]
public object SessionId get; set;
public class Header
[XmlElement(Namespace = "http://www.s1.com/info/")]
public SessionInfo SessionInfo get; set;
public class LoginResponse
[XmlElement(Namespace = "")]
public object Result get; set;
public class Body
[XmlElement(Namespace = "http://www.s1.com/info/")]
public LoginResponse LoginResponse get; set;
[XmlAttribute("encodingStyle", Namespace = "http://schemas.xmlsoap.org/soap/envelope/", Form = XmlSchemaForm.Qualified)]
public string EncodingStyle get; set;
[XmlRoot(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope
[XmlElement]
public Header Header get; set;
[XmlElement]
public Body Body get; set;
您可以看到一个工作演示 here。我对源 XML 进行了一项更改 - 我将 Result
值从 boolean
更改为 true
,否则您将收到异常,因为 boolean
不是该类型的有效值。
【讨论】:
非常感谢您不仅提供了一个有效的答案,还感谢您的解释,我还在学习,所以它对我非常有用!以上是关于由于命名空间而无法反序列化 xml的主要内容,如果未能解决你的问题,请参考以下文章
Jackson XML - 使用命名空间前缀反序列化 XML
反序列化自定义 XML 时出现 InvalidOperationException(缺少命名空间)