问题
I need to interact with a SOAP service and am having a lot of trouble doing so; would really appreciate any pointers on this. The original error message was:
org.apache.axis2.databinding.ADBException: Any type element type has not been given
After some research, it turns out that this is a disagreement between SUDS and the server has to how deal with
type="xsd:anyType"
on the element in question.
I've confirmed using SOAPUI and after advice that the problem can be fixed by taking these steps:
- Adding xsi:type="xsd:string" to each element which causes problems
- Adding xmlns:xsd="http://www.w3.org/2001/XMLSchema" to the SOAP Envelope
So, where SUDS currently does this:
<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>
it should instead produce this:
<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>
Is there a correct way to do this? I've seen suggestions of using ImportDoctor or MessagePlugins, but haven't really grokked how to achieve the desired effect.
回答1:
The solution I found was to use a MessagePlugin to essentially manually fix up the XML just before sending. I'd hoped there was something more elegant, but at least this works:
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'))
回答2:
It's sad and hilarious, like a lot of things about this particular library, but here's the exact answer:
http://lists.fedoraproject.org/pipermail/suds/2011-September/001519.html
from the above:
soapenv = soapenv.encode('utf-8')
plugins.message.sending(envelope=soapenv)
becomes:
soapenv = soapenv.encode('utf-8')
ctx = plugins.message.sending(envelope=soapenv)
soapenv = ctx.envelope
basically, it's a bug in the implementation, and you can patch it yourself by editing the line that runs the plugin to actually return the plugin's results, but I'm not aware of a patched and updated version of SUDS that fixes this yet (tho I haven't looked closely for it).
来源:https://stackoverflow.com/questions/10916433/adding-xsitype-and-envelope-namespace-when-using-suds