使用多个命名空间反序列化肥皂响应
Posted
技术标签:
【中文标题】使用多个命名空间反序列化肥皂响应【英文标题】:Deserialize soap response with multiple namespaces 【发布时间】:2020-01-11 20:10:04 【问题描述】:我很难反序列化下面的肥皂响应。 我假设它是因为多个命名空间或者可能是因为复杂类型(序列化数组)
Soapformatter 抛出一个对象引用异常,其他更多手动反序列化返回一个空对象。在这一点上,我只能假设我没有正确标记我的对象。构建下面的 BatchResponse 对象以便它可以从此响应反序列化的正确方法是什么?
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">https://example.com/operations/fetch/BatchResponse</a:Action>
</s:Header>
<s:Body>
<BatchResponse xmlns="https://example.com/operations">
<BatchResult xmlns:b="https://example.com/responses" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<b:FailureMessages xmlns:c="http://schemas.microsoft.com/2003/10/Serialization/Arrays" i:nil="true" />
<b:FailureType i:nil="true" />
<b:ProcessedSuccessfully>true</b:ProcessedSuccessfully>
<b:SessionId>1961810</b:SessionId>
<b:TotalPages>38</b:TotalPages>
</BatchResult>
</BatchResponse>
</s:Body>
</s:Envelope>
还假设 Soapformatter 继续抛出异常 - “xpath”到 BatchResponse 对象以便我可以提取和反序列化的正确方法是什么?
谢谢
【问题讨论】:
下面的解决方案有效,但当命名空间包含两个句点和一个破折号时 - 例如 example.test-site.com - 不知道为什么! 【参考方案1】:尝试以下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication131
class Program
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(Envelope));
Envelope envelope = (Envelope)serializer.Deserialize(reader);
[XmlRoot(ElementName = "Envelope", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public class Envelope
[XmlElement(ElementName = "Header", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public Header header get; set;
[XmlElement(ElementName = "Body", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public Body body get; set;
[XmlRoot(ElementName = "Header", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public class Header
[XmlElement(ElementName = "Action", Namespace = "http://www.w3.org/2005/08/addressing")]
public Action action get; set;
[XmlRoot(ElementName = "Action", Namespace = "http://www.w3.org/2005/08/addressing")]
public class Action
[XmlAttribute(AttributeName = "mustUnderstand", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public int mustUnderstand get; set;
[XmlText]
public string value get;set;
[XmlRoot(ElementName = "Body", Namespace = "")]
public class Body
[XmlElement(ElementName = "BatchResponse", Namespace = "https://example.com/operations")]
public BatchResponse batchResponse get; set;
[XmlRoot(ElementName = "BatchResponse", Namespace = "https://example.com/operations")]
public class BatchResponse
[XmlElement(ElementName = "BatchResult", Namespace = "https://example.com/operations")]
public BatchResult batchResult get; set;
[XmlRoot(ElementName = "BatchResult", Namespace = "https://example.com/operations")]
public class BatchResult
[XmlElement(ElementName = "FailureMessages", Namespace = "https://example.com/responses")]
public string failureMessages get; set;
[XmlElement(ElementName = "FailureType", Namespace = "https://example.com/responses")]
public string failureType get; set;
[XmlElement(ElementName = "ProcessedSuccessfully", Namespace = "https://example.com/responses")]
public Boolean processedSuccessfully get; set;
[XmlElement(ElementName = "SessionId", Namespace = "https://example.com/responses")]
public string sessionId get; set;
[XmlElement(ElementName = "TotalPages", Namespace = "https://example.com/responses")]
public int totalPages get; set;
【讨论】:
效果太棒了!谢谢你。有没有一种方法可以仅从 Body(即实际对象本身)反序列化而不处理整个信封? XML 序列化不需要所有属性都可以工作。只有公共属性被序列化和反序列化。您需要身体的所有父母,但不是每个父母中的所有属性。 感谢您的澄清。我想问这是否有必要。但是我发现它仍然不适合我。出于隐私原因,我在示例中修改了命名空间域名。用我的域名它不起作用。这似乎与拥有更复杂的域名有关。我重建了整个示例,当使用 example.com/operations 时(如上所述)它可以工作。但是,如果我用example.test-site.com/operations 切换它,它会在 BatchResponse 对象上序列化为 NULL!为什么会这样?我能做什么? 它看起来像是产生问题的“子域”。 test-site.com 有效。 example.test-site.com 不起作用 我无法看到您提供的链接,因为我被阻止了。直到稍后才能查看链接。没有得到对象的五个原因 1)命名空间是错误的。 2) 元素名称错误。它区分大小写 3) 属性不公开。 4)您使用了错误的类型元素/属性 5)您有数组。【参考方案2】:您可以使用local-name()
忽略xpath 中的命名空间
//*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='BatchResponse']
【讨论】:
以上是关于使用多个命名空间反序列化肥皂响应的主要内容,如果未能解决你的问题,请参考以下文章
XmlSerializer c++ 使用多个命名空间反序列化
c# XmlSerializer 反序列化器缺少默认命名空间