Python suds 错误的命名空间前缀在SOAP请求中

2024-09-27 04:20:49 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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>,因为它属于.xsd中定义的命名空间...GrantaBaseTypes

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

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

更新

我处理了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源代码的更聪明的解决方案。

谢谢

亚历克斯


Tags: 文件selfcomrefhttpwww空间element
3条回答

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

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

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

源代码中的修复“正确地”解决了问题,但是由于我希望每次去寻找另一个解决方案时都不应用修复就可以升级。。。。

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

编写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()
Provides the plugin with the opportunity to inspect/modify the envelope Document before it is sent.

相关问题 更多 >

    热门问题