【问题标题】:Savon ignores namespace_identifier attributeSavon 忽略命名空间标识符属性
【发布时间】:2016-10-21 14:26:27
【问题描述】:

我正在尝试重写由 savon body 命名空间编写的 - ins0 我有这个客户端变量:

client = Savon.client(wsdl: "https://integcert.synxis.com/interface/Contracts/ChannelConnect2004.wsdl", log_level: :debug, log: true, pretty_print_xml: true, env_namespace: :soapenv, namespaces: {"xmlns:soapenv": "http://schemas.xmlsoap.org/soap/envelope/", "xmlns:head": "http://htng.org/1.1/Header/","xmlns:ns": "http://www.opentravel.org/OTA/2003/05"}, convert_request_keys_to: :none, namespace_identifier: "ns", element_form_default: :qualified)

当我在做请求时:

client.call(:ping, soap_header: { "head:HTNGHeader": { "head:From": { "head:Credential": { "head:userName": "******", "head:password":"*****" }}}}, message: {"ns:EchoData": "TestData"})

我有这个soap rq body:

    <soapenv:Body>
    <ins0:OTA_PingRQ>
      <ns:EchoData>TestData</ns:EchoData>
    </ins0:OTA_PingRQ>
  </soapenv:Body>

这个ins0是从哪里来的?

当我尝试使用namespace_identifier: nil 参数定义客户端并执行此类请求时:

client.call(:ping, soap_header: { "head:HTNGHeader": { "head:From": { "head:Credential": { "head:userName": "******", "head:password":"*****" }}}}, message: {"ns:OTA_PingRQ": {"ns:EchoData": "TestData"}})

我有这个soap rq body:

 <soapenv:Body>
<OTA_PingRQ>
  <ns:OTA_PingRQ>
    <ns:EchoData>TestData</ns:EchoData>
  </ns:OTA_PingRQ>
</OTA_PingRQ>

我想要的正确身体是:

<soapenv:Body>   
   <ns:OTA_PingRQ>
   <ns:EchoData>TestData</ns:EchoData>
   </ns:OTA_PingRQ>
</soapenv:Body>

任何想法如何删除额外的嵌套 OTA_PingRQnode 或用自定义替换 ins0 命名空间?

【问题讨论】:

  • 请发布完整的 XML,包括 SOAP:envelope。命名空间前缀 ins0 必须已在 SOAP 信封中声明。如果 ins0 和 ns 都定义为“opentravel.org/OTA/2003/05”,那么请求将是有效的。我建议使用 SOAP UI 来验证和测试您生成的 SOAP 请求。

标签: ruby-on-rails soap wsdl savon


【解决方案1】:

您添加命名空间的想法在逻辑上是正确的,但看起来 Savon 并不想在任何地方都使用它们。它更喜欢使用 WSDL 中的名称空间。我尝试了element_form_default: :qualified 和element_form_default: :unqualified,但它仍然每次都将ins0 作为OTA_PingRQ 节点的命名空间。我想如果它想要ins0,那么让我们使用ins0。 我查看了可用名称空间列表,并为标题找到了合适的名称空间。不知道为什么 Savon 不想自动为头节点指定命名空间,所以我们必须手动将其指定为 ins1。

这是配置的工作版本:

client = Savon.client(
  wsdl: "https://integcert.synxis.com/interface/Contracts/ChannelConnect2004.wsdl", 
  log_level: :debug, 
  log: true, 
  pretty_print_xml: true, 
  namespace_identifier: :ins0, 
  element_form_default: :qualified,
  soap_header: { 
    "ins1:HTNGHeader": { 
      "ins1:From": { 
        "ins1:Credential": { 
           "ins1:userName": "******", 
           "ins1:password":"*****" 
        }
      }
    }
  }
)

client.call(:ping, message: {"EchoData": "TestData"})

请求:

<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ins0="http://www.opentravel.org/OTA/2003/05" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ins1="http://htng.org/1.1/Header/">
  <env:Header>
    <ins1:HTNGHeader>
      <ins1:From>
        <ins1:Credential>
          <ins1:userName>******</ins1:userName>
          <ins1:password>*****</ins1:password>
        </ins1:Credential>
      </ins1:From>
    </ins1:HTNGHeader>
  </env:Header>
  <env:Body>
    <ins0:OTA_PingRQ>
      <ins0:echoData>TestData</ins0:echoData>
    </ins0:OTA_PingRQ>
  </env:Body>
</env:Envelope>

回复:

<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>
    <OTA_PingRS xmlns="http://www.opentravel.org/OTA/2003/05" PrimaryLangID="en">
      <Errors>
        <Error Type="4" ShortText="Login failed"/>
      </Errors>
      <EchoData/>
    </OTA_PingRS>
  </soap:Body>
</soap:Envelope>

编辑:在客户端配置中提供soap_header,因为它是更有效的方式。

【讨论】:

    【解决方案2】:

    还有另一种附加 namespace_identifier 的方法。 首先在 Savon 客户端设置 namespace_identifier: nil。

    basic_auth = [username, password]
    client = Savon.client(
        wsdl:"https://integcert.synxis.com/interface/ChannelConnect2004.wsdl",
        namespace: {},
        env_namespace: 'soapenv',
        namespace_identifier: nil,
        basic_auth: basic_auth,
        logger: Rails.logger,
        log: true,
        soap_version: 2,
        pretty_print_xml: true,
        convert_request_keys_to: :camelcase,
        namespaces: {
            'xmlns:soap' => 'http://example.com/soap-envelope',
            'xmlns:glob' => 'http://example.com/Global'
       }
    )
    

    现在同时调用操作集message_tag response = client.call(:operation_name, message_tag: 'glob:OTA_PingRQ', message: {"EchoData": "TestData"})

    输出:

    <soapenv:Body>   
        <glob:OTA_PingRQ>
        <EchoData>TestData</ns:EchoData>
        </glob:OTA_PingRQ>
    </soapenv:Body>
    For Outoput like:
    <soapenv:Body>   
        <ns:OTA_PingRQ>
        <ns:EchoData>TestData</ns:EchoData>
        </ns:OTA_PingRQ>
    </soapenv:Body>
    
    client call will be same but in client config add **element_form_default: :qualified**
    

    【讨论】:

      猜你喜欢
      • 2018-10-19
      • 2017-01-28
      • 2015-10-26
      • 1970-01-01
      • 1970-01-01
      • 2021-10-02
      • 2010-12-24
      • 2011-12-05
      • 2015-02-18
      相关资源
      最近更新 更多