7

我使用 python/suds 来实现客户端,但在发送的 SOAP 标头中,element ref=对于 wsdl 中定义的特定类型的参数,我得到了错误的命名空间前缀。

.wsdl 引用数据类型 .xsd 文件,见下文。问题在于函数GetRecordAttributes及其类型的第一个参数gbt:recordReferences

文件:browse2.wsdl

<xsd:schema targetNamespace="http://www.grantadesign.com/10/10/Browse" xmlns="http://www.grantadesign.com/10/10/Browse" xmlns:gbt="http://www.grantadesign.com/10/10/GrantaBaseTypes" elementFormDefault="qualified" attributeFormDefault="qualified">
<xsd:import schemaLocation="grantabasetypes2.xsd" namespace="http://www.grantadesign.com/10/10/GrantaBaseTypes"/>
<xsd:element name="GetRecordAttributes">
      <xsd:complexType>
          <xsd:sequence>
              <xsd:element ref="gbt:recordReferences">
              </xsd:element>

参考文件:grantabasetypes2.xsd

<element name="recordReferences">
  <complexType>
    <sequence>
      <element name="record" minOccurs="0" maxOccurs="unbounded" type="gbt:MIRecordReference"/>
    </sequence>
  </complexType>
</element>

由 suds 发送的 SOAP 请求:

<SOAP-ENV:Envelope xmlns:ns0="http://www.grantadesign.com/10/10/GrantaBaseTypes" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns2="http://www.grantadesign.com/10/10/Browse" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <ns1:Body>
      <ns2:GetRecordAttributes>
         <ns2:recordReferences>
            <ns0:record>
            </ns0:record>
         </ns2:recordReferences>
      </ns2:GetRecordAttributes>
   </ns1:Body>
</SOAP-ENV:Envelope>

问题<ns2:recordReferences>前缀错误,应该是 <ns0:recordReferences>因为它属于...GrantaBaseTypes .xsd 中定义的命名空间。

这发生ref=在 wsdl 中定义的所有参数上。如何自动修复?

注意:我通过 curl 手动发送 xml SOAP 请求来检查服务是否接受了“好”前缀。

更新

我干预了 SUDS 源代码,下面的经验修复强制所有具有ref=属性的元素假定 ref-ed 命名空间(以前,它们采用模式根命名空间或其他任何东西tns):

文件:/suds/xsd/sxbase.py

class SchemaObject(object):
....
    def namespace(self, prefix=None):

        ns = self.schema.tns

#FIX BEGIN
        if self.ref and self.ref in self.schema.elements.keys():
            ns = self.ref
#FIX END

适用于我的服务,但我不确定它是否会破坏其他东西。我更喜欢不更改 SUDS 源代码的更智能的解决方案。

谢谢,

亚历克斯

4

4 回答 4

8

编写一个Suds 插件以在发送 XML 之前对其进行修改。

from suds.client import Client
from suds.plugin import MessagePlugin

class MyPlugin(MessagePlugin):
    def marshalled(self, context):
        #modify this line to reliably find the "recordReferences" element
        context.envelope[1][0][0].setPrefix('ns0')

client = Client(WSDL_URL, plugins=[MyPlugin()])

引用 Suds 文档:

marshalled()
为插件提供在发送前检查/修改信封文档的机会。

于 2012-04-19T20:37:15.017 回答
2

使用 suds 访问 BizTalk/IIS SOAP 服务时,我遇到了完全相同的问题。从我从 WSDL 中可以看出,当有一个“complexType”不属于“targetNamespace”(它有它自己的)时,就会发生这种情况,它有一个也是 complexType 的子项,但没有设置命名空间。在 BizTalk 中,这意味着子级应该与父级属于同一个命名空间,但 Suds 似乎认为它应该是 targetNamespace 的一部分......

源代码中的修复“正确”地解决了这个问题,但是因为我希望能够在每次我寻求另一个解决方案时不应用修复的情况下进行升级......

我的解决方案是跳过 Suds,只复制原始 XML,将其用作模板并将值复制到其中……不漂亮,但至少简单。在我看来,添加插件的解决方案同样是硬编码的,而且可能更难维护。

于 2013-03-22T08:35:33.280 回答
1

您可以自己构建肥皂消息并用于SoapClient发送消息:

sc = SoapClient(cli.service.XXXMethod.client,cli.service.XXXMethod.method)
sc.send(some_soap_doc)
于 2012-06-13T07:58:59.373 回答
-1

我更喜欢正则表达式:)

import re

class EnvelopeFixer(MessagePlugin):
    def sending(self, context):
        # rimuovi i prefissi
        context.envelope = re.sub( 'ns[0-9]:', '', context.envelope )
        return context.envelope
于 2013-09-25T09:37:04.357 回答