首页 文章

python suds在SOAP请求中错误的名称空间前缀

提问于
浏览
5

我使用python / suds来实现一个客户端,我在发送的SOAP头中得到错误的名称空间前缀,用于wsdl中由 element ref= 定义的特定参数类型 .

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

File: 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>

Referenced File : grantabasetypes2.xsd

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

SOAP Request sent by suds:

<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>

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

对于wsdl中 ref= 定义的所有参数,都会发生这种情况 . 如何自动修复?

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

UPDATE

我使用SUDS源代码进行干预,以下经验修正强制所有具有 ref= 属性的元素假定引用的命名空间(以前,它们采用模式根命名空间或其他 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 回答

  • -1

    编写Suds plugin以在发送之前修改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()为插件提供在发送之前检查/修改信封Document的机会 .

  • 1

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

    源代码中的修复解决了“正确”的问题,但是因为我希望每次去另一个解决方案时能够升级而不应用修复程序....

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

  • 8

    您可以自己构建soap消息并使用 SoapClient 发送消息:

    sc = SoapClient(cli.service.XXXMethod.client,cli.service.XXXMethod.method)
    sc.send(some_soap_doc)
    
  • 2

    我更喜欢正则表达式:)

    import re
    
    class EnvelopeFixer(MessagePlugin):
        def sending(self, context):
            # rimuovi i prefissi
            context.envelope = re.sub( 'ns[0-9]:', '', context.envelope )
            return context.envelope
    

相关问题