Skip to main content
 首页 » 编程设计

python之添加 xsi :type and envelope namespace when using SUDS

2025年05月04日9haluo1

我需要与 SOAP 服务进行交互,但遇到了很多麻烦;非常感谢对此的任何指示。原来的错误信息是:

org.apache.axis2.databinding.ADBException: Any type element type has not been given 

经过一番研究,原来这是SUDS和服务器之间的分歧,要如何处理

type="xsd:anyType" 

关于有问题的元素。

我已确认使用 SOAPUI,并在收到建议后可以通过执行以下步骤解决问题:

  1. 将 xsi:type="xsd:string"添加到导致问题的每个元素
  2. 将 xmlns:xsd="http://www.w3.org/2001/XMLSchema"添加到 SOAP 信封

因此,SUDS 目前这样做的地方:

<SOAP-ENV:Envelope ... xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
<ns3:Body> 
  <ns0:method> 
     <parameter> 
        <values> 
           <table> 
              <key>EMAIL_ADDRESS</key> 
              <value>example@example.org</value> 
           </table> 
        </values> 
     </parameter> 
  </ns0:method> 

它应该产生这个:

<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" ... xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
 
  <ns3:Body> 
  <ns0:method> 
     ... 
     <parameter> 
        <values> 
           <table> 
              <key xsi:type="xsd:string">EMAIL_ADDRESS</key> 
              <value xsi:type="xsd:string">example@example.org</value> 
           </table> 
        </values> 
     </parameter> 
  </ns0:method> 

有正确的方法吗?我看过使用 ImportDoctor 或 MessagePlugins 的建议,但还没有真正弄明白如何达到预期的效果。

请您参考如下方法:

我找到的解决方案是使用 MessagePlugin 在发送前手动修复 XML。我希望有更优雅的东西,但至少这是有效的:

class SoapFixer(MessagePlugin): 
 
    def marshalled(self, context): 
        # Alter the envelope so that the xsd namespace is allowed 
        context.envelope.nsprefixes['xsd'] = 'http://www.w3.org/2001/XMLSchema' 
        # Go through every node in the document and apply the fix function to patch up incompatible XML.  
        context.envelope.walk(self.fix_any_type_string) 
 
    def fix_any_type_string(self, element): 
        """Used as a filter function with walk in order to fix errors. 
        If the element has a certain name, give it a xsi:type=xsd:string. Note that the nsprefix xsd must also 
         be added in to make this work.""" 
        # Fix elements which have these names 
        fix_names = ['elementnametofix', 'anotherelementname'] 
        if element.name in fix_names: 
            element.attributes.append(Attribute('xsi:type', 'xsd:string'))