如何反序列化 C# 对象中复杂的 XML 格式并读取它以使用其值?

Posted

技术标签:

【中文标题】如何反序列化 C# 对象中复杂的 XML 格式并读取它以使用其值?【英文标题】:How to deserialize a difficult XML format in C# object and read it in order to use its values? 【发布时间】:2021-01-30 18:24:20 【问题描述】:

我有一个非常难格式化的 XML 文档,我想阅读它并使用它的参数。

这是我要反序列化的 XML

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope
  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
      <APIResponse xmlns="https://testwebservice.com/">
          <Result>Api Result Message</Result>
      </APIResponse>
    </soap:Body>
</soap:Envelope>

我已经尝试了一些在其他问题中找到的代码示例

APIResponse envelopeClass = new APIResponse();
XmlSerializer serializer = new XmlSerializer(typeof(APIResponse), new XmlRootAttribute("Envelope"));
StringReader stringReader = new StringReader(xmlString);
envelopeClass = (APIResponse)serializer.Deserialize(stringReader);

但到目前为止没有任何帮助,因为我收到这样的错误:

System.InvalidOperationException: 'XML 文档 (1, 42) 中存在错误。' 内部异常 InvalidOperationException: 不是预期的。

这些是迄今为止我在 Visual Studio 中通过 选择性粘贴 按钮使用的类。

[System.SerializableAttribute()]
[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

   public EnvelopeBody bodyField  get; set; 


[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://schemas.xmlsoap.org/soap/envelope/")]
public partial class EnvelopeBody

   [System.Xml.Serialization.XmlElementAttribute(Namespace = "https://testwebservice.com/")]
   public  APIResponse aPIResponseField  get; set; 


[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="https://testwebservice.com/")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="https://testwebservice.com/", IsNullable=false)]
public partial class APIResponse 

   public string resultField  get; set; 


尽管如此,我仍然不明白为什么会出现上述错误,但我想指出我还没有完全理解这一切是如何工作的。 无论如何,如果有人可以提供帮助,我将不胜感激。

请告诉我哪些是我应该在这个 XML 格式文档中使用的正确类以及如何反序列化它。

【问题讨论】:

Xml 序列化很难调试。我通常注释掉 c# 类的部分以查找错误。如果 XML 中存在标签并且没有 c# 类属性,则不会生成错误。我通常首先在 c# 类中注释掉根类中的所有属性,以确保 xml 没有错误。然后移除 cmets,直到我确定问题所在。 【参考方案1】:

您所称的“困难 XML 格式”实际上是标准 SOAP (Simple Object Access Protocol) 消息。 SOAP 被用作基于 XML 的 Web 服务的通信协议,它首先让您想到您可以为 Web 服务添加一个服务引用,您可以从其中获取此 XML 内容。如果您从 Web 资源中获取此 XML 内容,请尝试将其添加为服务参考。

如果没有,并且您刚刚以某种方式结束了此 XML 内容,尽管有一些示例说明如何通过解析并仅序列化其中的一部分从 xml 中获取响应对象,这就是我的假设是一种更精细、更安全的方式来实现它。

添加 NuGet 引用:Microsoft.Web.Services3

将类ApiResponse更改如下(将名称resultField改为Result)

[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "https://testwebservice.com/")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "https://testwebservice.com/", IsNullable = false)]
public partial class APIResponse

    public string Result  get; set; 

然后使用 SoapEnvelope 类及其方法获取ApiResponse 对象,例如:

using Microsoft.Web.Services3;

. . .
. . .

SoapEnvelope envelope = new SoapEnvelope();
envelope.LoadXml(xmlString);
APIResponse apiResponse = (APIResponse)envelope.GetBodyObject(typeof(APIResponse));

. . .
. . .

【讨论】:

我可以在不使用 Microsoft.WebServices3 包的情况下使用这些类吗? 因为它有依赖问题 我认为不是。您可以检查其他响应(this)(https://***.com/questions/6838504/parsing-a-soap-response-with-c-sharp), ot [this 了解 XML 的执行方式。

以上是关于如何反序列化 C# 对象中复杂的 XML 格式并读取它以使用其值?的主要内容,如果未能解决你的问题,请参考以下文章

C#中具有复杂元素的Xml反序列化[重复]

C# XML对象序列化反序列化 - PEPE YU

需要帮助将 XML 文件反序列化为对象 C#

如何将 XML 反序列化为 C# 中的对象? [复制]

如何使用 C# 映射反序列化 XML 文档

一个可序列化的C#对象,如何转成一个XML格式的文件或字符串