如何从 nusoap 服务返回的 XML 反序列化对象?

Posted

技术标签:

【中文标题】如何从 nusoap 服务返回的 XML 反序列化对象?【英文标题】:How can I deserialize an object from an XML returned from a nusoap service? 【发布时间】:2019-11-21 22:44:25 【问题描述】:

我正在尝试从 NuSoap 服务返回的 Xml 中反序列化一个对象。 我收到了带有 WSDL 文件的服务,并尝试将它实施到我的项目中。问题是 WSDL 文件似乎损坏了。 我可以通过 SoapUI 访问 Web 服务。我也可以成功地将我的请求手动填充到 XML 表单中。作为对请求的回应,我从服务中返回了一个 Xml。

我已经为一些请求创建了类。我可以成功地序列化和发布它们并获得我的 Xml 响应。现在我的实际问题开始了。我想反序列化这个响应。

<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="urn:LicenseManagement">
    <SOAP-ENV:Body>
       <ns1:GetErrorCodesResponse xmlns:ns1="urn:LicenseManagement">
        <RETURN xsi:type="tns:ReturnGetErrorCodes">
          <RC xsi:type="xsd:int">0</RC>
          <DATA xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType=":[55]">
           <item xsi:type="xsd:string">OK</item>
           <item xsi:type="xsd:string">database unavailable</item>
           <item xsi:type="xsd:string">...</item>
          </DATA>
        </RETURN>
       </ns1:GetErrorCodesResponse>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

我从实现其中一个响应的类开始。 我可以设法反序列化这个 XML 的 Envelope、Body、GetErrorResponse 部分。当我到达返回部分时,我得到一个空值。

我知道我可以使用 DataSet 来解决我的问题,但这需要每个响应都有一个 MappingProfile。

try

   //
   GetErrorCodesRequestModel request = new GetErrorCodesRequestModel()
   
     Username = "xxx" ,
     Password = "zzZzZ"
   ;
   var res = XmlExtension.SerializeToString(request);

   XmlDocument soapEnvelopeXml = CreateSoapEnvelope(res);

   HttpWebRequest webRequest = CreateWebRequest(command , "POST");
   InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml , webRequest);

   IAsyncResult asyncResult = webRequest.BeginGetResponse(null , null);
   asyncResult.AsyncWaitHandle.WaitOne();

   string soapResponse = string.Empty;
   using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
   using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
   
      soapResponse = rd.ReadToEnd();
   

// this is the part where I have to deserialize the soapResponse

   var deserialized = XmlExtension.Deserialize<Envelope>(soapResponse);

// deserialized contains information til RETURN
// important information missing

我的课程看起来像这个 atm。

[XmlRoot(ElementName = "RC")]
public class RC

   [XmlAttribute(AttributeName = "type" , Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
   public string Type  get; set; 
   [XmlText]
   public string Text  get; set; 


[XmlRoot(ElementName = "item")]
public class Item

   [XmlAttribute(AttributeName = "type" , Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
   public string Type  get; set; 
   [XmlText]
   public string Text  get; set; 


[XmlRoot(ElementName = "DATA")]
public class DATA

   [XmlElement(ElementName = "item")]
   public Item[] Item  get; set; 
   [XmlAttribute(AttributeName = "type" , Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
   public string Type  get; set; 
   [XmlAttribute(AttributeName = "arrayType" , Namespace = "http://schemas.xmlsoap.org/soap/encoding/")]
   public string ArrayType  get; set; 


[XmlType(AnonymousType = true , IncludeInSchema = true)]
[XmlRoot(ElementName = "RETURN", Namespace = "tns:ReturnGetErrorCodes" , IsNullable = false)]
public class RETURN

   [XmlElement(ElementName = "RC")]
   public RC RC  get; set; 
   [XmlElement(ElementName = "DATA")]
   public DATA DATA  get; set; 
   [XmlAttribute(AttributeName = "type" , Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
   public string Type  get; set; 


[XmlRoot(ElementName = "GetErrorCodesResponse" , Namespace = "urn:LicenseManagement")]
public class GetErrorCodesResponse

   [XmlElement(ElementName = "RETURN")]
   public RETURN RETURN  get; set; 
   [XmlAttribute(AttributeName = "ns1" , Namespace = "http://www.w3.org/2000/xmlns/")]
   public string Ns1  get; set; 


[XmlRoot(ElementName = "Body" , Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Body

   [XmlElement(ElementName = "GetErrorCodesResponse" , Namespace = "urn:LicenseManagement")]
   public GetErrorCodesResponse GetErrorCodesResponse  get; set; 


[XmlRoot(ElementName = "Envelope" , Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope

   [XmlElement(ElementName = "Body" , Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
   public Body Body  get; set; 

   [XmlAttribute(AttributeName = "SOAP-ENV" , Namespace = "http://www.w3.org/2000/xmlns/")]
   public string SOAPENV  get; set; 

   [XmlAttribute(AttributeName = "xsd" , Namespace = "http://www.w3.org/2000/xmlns/")]
   public string Xsd  get; set; 

   [XmlAttribute(AttributeName = "xsi" , Namespace = "http://www.w3.org/2000/xmlns/")]
   public string Xsi  get; set; 

   [XmlAttribute(AttributeName = "SOAP-ENC" , 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; 

【问题讨论】:

您缺少名称空间“SOAP-ENV”的定义。 其实不是。我只是把那部分删掉了。那就编辑吧^^ 我们需要带有命名空间定义的行来提供帮助。没有命名空间,xml 就会被破坏。 我再次编辑它并添加了我得到的完整 xml 和我为反序列化创建的类。 【参考方案1】:

解决这些问题的最佳方法是使用示例数据创建类并进行序列化。然后将您的序列化 xml 与原始 xml 进行比较

        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        
            Envelope envelope = new Envelope() 
                Body = new Body() 
                    GetErrorCodesResponse = new GetErrorCodesResponse() 
                        Ns1 = "urn:LicenseManagement",
                        RETURN = new RETURN() 
                            Type = "tns:ReturnGetErrorCodes",
                            RC = new RC() 
                                Type = "xsd:int",
                                Text = "0"
                            ,
                            DATA = new DATA()  
                                Type = "SOAP-ENC:Array",
                                ArrayType = ":[55]",
                                Item = new Item[] 
                                    new Item()  Type = "xsd:string", Text = "OK",
                                    new Item()  Type = "xsd:string", Text = "database unavailable",
                                    new Item()  Type = "xsd:string", Text = "..."
                                
                            
                        
                    
                
            ;
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            XmlWriter writer = XmlWriter.Create(FILENAME, settings);
            XmlSerializer serializer = new XmlSerializer(typeof(Envelope));

            serializer.Serialize(writer, envelope);
        
    

【讨论】:

我可以用一种非常丑陋、不优雅的方式解决我的问题。 StringReader reader = new StringReader(soapResult);数据集 ds = new DataSet(); ds.ReadXml(阅读器); var deserialized = XmlExtension.Deserialize(ds.GetXml()); 这并不能解决问题。你只会一团糟。 DataSet ReadXml 类在您获得的 XML 超过三个级别的子标签时会产生一个无用的碎片数据集。一旦碎片化,您就无法重新组合以获得有用的数据。 我注意到了。它在发布的东西上效果很好,但是当我尝试用“更大”的对象以同样的方式做这件事时,我得到了一个例外。我想我将不得不自己解析它。失去我的耐心atm:D 解析xml的方法有很多。我根据情况使用所有这些。 Net XML 库在命名空间方面存在问题,并且并不总是有效。我在周末尝试修复课程并能够序列化,但随后无法反序列化结果。我不确定您是否可以修改现有的 xml。您可能想要修改生成文件的 xml 代码。否则,我同意您可能需要使用 Net Library Xml(或 XML Linq)编写自己的自定义解析器。如果您需要其他帮助,请告诉我。我的偏好是使用 XML Linq。 当然,我会询问我是否需要进一步的帮助并报告我是否也能取得进展。非常感谢您尝试 mate。

以上是关于如何从 nusoap 服务返回的 XML 反序列化对象?的主要内容,如果未能解决你的问题,请参考以下文章

反序列化后无法获取从xml文件返回的项目列表

PHP Soap - 使用 nusoap 保存 xml 服务器端

如何在C#中解析/反序列化从rest服务返回的JSON

如何将简单的类序列化/反序列化为 XML 并返回

从字符串反序列化 XML

如何从动态对象中获取反序列化的 xml 属性