Chapter 4. Make a SOAP client with Python.

Table of Contents
4.1. Using SOAPpy to consume a JWSDP web service.
4.1.1. How to make a simple client
4.1.2. How to handle complex type returned by a remote procedure, using Python and SOAPpy.
4.1.3. Handy: let SOAPpy extract all the method available from a WSDL
4.2. Python XML HTTP Post to send a SOAP message to a JWSDP or to a .NET web service.
4.2.1. XML HTTP Post to my Java WSDP web service.
4.2.2. Build a SOAP message using DOM with PyXml, and post it to a web service.
4.2.3. Post an XML SOAP message to a .NET web service.
4.2.4. Consume a .NET web service with Python, a more complete example.
4.3. Python ZSI SOAP client for JWSDP and .NET web service.
4.3.1. Interoperability between a Java WSDP web service and a Python ZSI client.
4.3.2. Deserialize complex type object returned by a Java WSDP web service using ZSI.
4.3.3. Use WSDL2py to generate the class needed to unmarshall array of simple type, or array of object returned by a JWSDP web service.
4.3.4. Use WSDL2py to consume an advanced .NET web service with Python and ZSI.

In this serie of section, you will find several interoperability examples using two important SOAP libraries for Python: SOAPpy and ZSI, to consume Java WSDP or .NET web services.

4.1. Using SOAPpy to consume a JWSDP web service.

Let's start using SOAPpy, it's a very easy and relatively powerfull maen to consume a web service from Python. I assume here you have a recent Python install plus all the required packages installed for the use of SOAPpy: fpconst and PyXML. To test your PyXML install, type the following code in your Python command-line:

>>> import xml
>>> 

If you don't have any error message, your package PyXML is correctly installed. Do the same check with fpconst:

>>> import fpconst
>>> 

And finally with SOAPpy:

>>> import SOAPpy
>>> 

If you encounter any error, just install the package needed.

4.1.2. How to handle complex type returned by a remote procedure, using Python and SOAPpy.

We just use the same template here, each call use the function _ns(), allowing to specify the namespace for the remote procedure (like in the wsdl). If you need to send a complex type as a parameter, shift to the section which explain how to consume a .NET web service using python.

# we start with the status() procedure, which return 
# the object rcxResponse containing some internal
# values of my RCX brick.
rcxResponse = server._ns(namespace).status()

print 'Rcx message: '.ljust(20) , rcxResponse.status + \
  '\nBattery level: '.ljust(20) , rcxResponse.battery + \
  '\nInternal clock: '.ljust(20) , rcxResponse.currentTime + \
  '\nMemory free: '.ljust(20) , rcxResponse.memory

# the function collInt() (returning an array of integer)
intarray = server._ns(namespace).collInt()

print 'Remote procedure collInt() returning an array of integer:'
for val in intarray :
  print val.rjust(5)

# the function collPos() (returning an array of PosCol object
PosColArray = server._ns(namespace).collPos()

print 'Remote procedure collPos() returning an array of PosCol object:'
for pc in PosColArray :
  print '[XPos]: '.ljust(10) + pc.XPos , '[YPos]: '.ljust(10) + pc.YPos

So we see how it is simple to use. The most important things are specify the namespace and the parameter name accordingly to the wsdl. With more experience, you will soon be able to easily find these info in any wsdl. And if you begin, just make a client with a well known tool and catch the SOAP message exchanged between your client and the web service you consume (eg: TcpTunnelGui). Knowing exactly the format of the SOAP message you have to send, it is easier to reproduce it in another language/platform and with other tools.

4.1.3. Handy: let SOAPpy extract all the method available from a WSDL

You can use the WSDL class to parse a WSDL and list, for you, all the methods available. And sometimes even the parameter name and type, took and returned by the methods. Test this code on a web service of your choice:

Example 4-2. How to parse a wsdl with SOAPpy.


from SOAPpy import WSDL

url = 'http://www.pascalbotte.be/rcx-ws/rcx'

# just use the path to the wsdl of your choice
wsdlObject = WSDL.Proxy(url + '?WSDL')

print 'Available methods:'
for method in wsdlObject.methods.keys() :
  print method
  ci = wsdlObject.methods[method]
  # you can also use ci.inparams
  for param in ci.outparams :
    # list of the function and type 
    # depending of the wsdl...
    print param.name.ljust(20) , param.type
  print