如何解析从文件加载的soap消息?

Posted

技术标签:

【中文标题】如何解析从文件加载的soap消息?【英文标题】:How to parse a soap message loaded from a file? 【发布时间】:2017-09-26 16:20:27 【问题描述】:

我需要将从磁盘加载的 SOAP 消息解析为生成的代理的类型。 WCF 在收到来自 http 服务器的消息时会执行此操作,因此我应该能够从磁盘执行此操作。

我使用 WCF 使用 Web 服务,我从远程 WSDL 生成代理客户端。

这是我从网络收到的 XML 结构(使用 System.ServiceModel.MessageLogging 记录),我想将其解析为生成的类 CRResponse。:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="urn:PourtuIntf" xmlns:ns2="ns2:PourtuIntf-IPourtu">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
      <ns2:GetCRResponse>
         <return>
            <ResultCode>0</ResultCode>
            <CR>
               <Theme SOAP-ENC:arrayType="ns1:ItemType[5]">
                  <item>
                     <Key/>
                     <Section SOAP-ENC:arrayType="ns1:Section[3]">
...

当我调用 Web 服务的“GetCR”操作时,消息被正确转换为 WCF 生成的代理客户端类型 GetCRResponse,但我不知道 WCF 是如何工作的,我需要从磁盘解析文件。

我试图以这种方式解析消息:

  GetCRResponse body;
  using (var xmlReader =  XmlReader.Create("Requests\\CR.xml"))
  
      Message m = Message.CreateMessage(xmlReader, int.MaxValue, MessageVersion.Soap11);
      body = m.GetBody<GetCRResponse>();
  

在 GeyBody 方法中引发此异常:

Expected element 'ActGetCRResponse' from namespace 'http://schemas.datacontract.org/2004/07/Pourtu.PourtuClient'.. Detecting 'Element' with name 'ActGetCRResponse', namespace 'urn:PourtuIntf-IPourtu'.

我尝试使用 SoapFormatter:

using ( FileStream fs = new FileStream("Requests\\CR.xml", FileMode.Open) )

    SoapFormatter formatter = new SoapFormatter();
    body = (ActGetCRResponse)formatter.Deserialize(fs);

..反序列化抛出以下异常:分析错误,没有与 xml 键 'ns2 GetCRResponse' 关联的程序集。

我无法使用 xml 序列化程序反序列化为 GetCRResponse,因为 SOAP-ENC:arrayType 属性需要由 soap 序列化程序解释。

【问题讨论】:

请贴出CR.xml的链接或全部内容,谢谢。 这里是整个 CR.xml:dropbox.com/sh/8lnwwg7ed7tunmm/AAD286dN8BHUrF2YYvjbPruna?dl=0,这里是完整的 WSDL:dropbox.com/s/gbdd3w3th0lon04/IPlotiservice.wsdl?dl=0 @abreneliere 如果基于 SOAP xml 创建一组对象类,我可以通过 XmlSerializer 将 SOAP 消息反序列化为 ActGetCRResponse 对象。如果这有帮助,我可以提供,如果不担心的话:) 使用从 wsdl 生成的代理类只会产生错误或空对象。 是的,我需要解析到代理类,因为我需要使用文件数据调用 Web 服务的操作。 【参考方案1】:

您应该能够在SoapReflectionImporter 的帮助下使用XmlSerializer 来完成此操作。

var importer = new SoapReflectionImporter("ns2:PourtuIntf-IPourtu");
var mapping = importer.ImportTypeMapping(typeof(GetCRResponse));
var serializer = new XmlSerializer(mapping);
var response = serializer.Deserialize(reader) as GetCRResponse;

SoapReflectionImporter 类提供类型映射到 SOAP 编码的消息部分,如 Web 服务描述中所定义 语言 (WSDL) 文档。仅在 Web 服务或客户端时使用 指定 SOAP 编码,如 SOAP 1.1 的第 5 节所述 规范。

以下命令用于从 WSDL 生成您的客户端合同

SvcUtil.exe IPlotiservice.wsdl /t:code /serviceContract

【讨论】:

是的,我添加了一个关于 DataContractSerializer 问题的帖子:***.com/questions/43741674/…【参考方案2】:

更新:

Message m = Message.CreateMessage(XmlReader.Create("C:\\testSvc\\login.xml"), int.MaxValue, MessageVersion.Soap11);
            SoapReflectionImporter importer = new SoapReflectionImporter(new SoapAttributeOverrides(), "urn:PlotiIntf-IPloti");
            XmlTypeMapping mapp = importer.ImportTypeMapping(typeof(ActGetCRResponse));
            XmlSerializer xmlSerializer = new XmlSerializer(mapp); 
            var o = (ActGetCRResponse)xmlSerializer.Deserialize(m.GetReaderAtBodyContents());

reference

【讨论】:

感谢您的帮助,但 XmlSerializer 不理解 SOAP-ENC:arrayType 以便将元素的内容解析为正确的类型。 @abreneliere 你试过使用DataContractSerializer吗? 是的,我为它添加了另一个帖子:***.com/questions/43741674/…

以上是关于如何解析从文件加载的soap消息?的主要内容,如果未能解决你的问题,请参考以下文章

PHP SoapClient over selfsigned certificate,SOAP-ERROR:解析WSDL:无法从'https://加载

SOAP-ERROR:解析WSDL:无法从'http://127.0.0.1/test/index?wsdl'加载:

如何用python解析soap消息体中的参数

如何在 iphone 的表视图上加载 Soap 响应

java怎么解析文本文件中的soap报文

如何修复解析器错误消息:无法加载类型?