In the following sections you will find code template to send a SOAP message "by hand" to a Java WSDP web service (document/literal). I will also use this technique to consume the Infobel web service.
It is relatively easy to send a file to a web server with Python. In the case of a JWSDP web service, do not forget to add the Content-type in the header of your message, so the call is accepted by the server. Again, this is a command-line example, and the SOAP response is printed without any parsing. I will show later how to use PyXml to parse the SOAP message in the case of the Infobel web service, because the data returned are much more complex.
If you want to test this code with my web service, check here if it is on-line. As usually, you can change the SOAP message, and consume another web service, by building a client with your favorite and well-known tool, and catch the SOAP message echanged between your client and the web service.
What about to build dynamically the soap message you have to post? Find below how to create a SOAP message with DOM using PyXml and Python.
# post an xml file, use DOM to build SOAP message
import sys, httplib
from xml.dom import implementation
from xml.dom.ext import PrettyPrint
import StringIO
# define namespaces used
ec = "http://schemas.xmlsoap.org/soap/encoding/"
soapEnv = "http://schemas.xmlsoap.org/soap/envelope/"
myns = "http://phonedirlux.homeip.net/types"
# DOM document
domdoc = implementation.createDocument(None, '', None)
# SOAP envelope namespace
seObj = domdoc.createElementNS(soapEnv, "SOAP-ENV:Envelope")
seObj.setAttributeNS(soapEnv, "SOAP-ENV:encodingStyle", ec)
# add it to the root
domdoc.appendChild(seObj)
header = domdoc.createElement("SOAP-ENV:Header")
seObj.appendChild(header)
body = domdoc.createElement("SOAP-ENV:Body")
readls = domdoc.createElementNS(myns, "ns1:readLS")
string_1 = domdoc.createElement("String_1")
string_1.appendChild(domdoc.createTextNode("Message created with PyXml, your e-mail"))
readls.appendChild(string_1)
body.appendChild(readls)
seObj.appendChild(body)
soapStr = StringIO.StringIO()
PrettyPrint(domdoc, soapStr)
# view the soap message
print soapStr.getvalue()
# construct the header and post
webservice = httplib.HTTP("www.pascalbotte.be")
webservice.putrequest("POST", "/rcx-ws/rcx")
webservice.putheader("Host", "www.pascalbotte.be")
webservice.putheader("User-Agent", "My post")
webservice.putheader("Content-type", "text/xml; charset=\"UTF-8\"")
webservice.putheader("Content-length", "%d" % len(soapStr.getvalue()))
webservice.putheader("SOAPAction", "\"\"")
webservice.endheaders()
webservice.send(soapStr.getvalue())
# get the response
statuscode, statusmessage, header = webservice.getreply()
print "Response: ", statuscode, statusmessage
print "headers: ", header
res = webservice.getfile().read()
print res
Let's see how to post a more advanced SOAP message to the Infobel web service, and also see how to parse the response using Python and PyXml (See the Section called Tip: a way to solve interoperability problem with a NuSoap client (for document/literal web service). in Chapter 2 for a description of the Infobel web service we will consume here). We are going to use Sax and so we need a handler. Before to create a handler, we need to know exactly the structure of the SOAP message returned by the web service. Let's take a look at the data hilighted in bold. in this simple example we will parse the records found and ignore the other fields (elements of the query, status, etc...).
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<SearchResponse xmlns="http://www.infobel.com/WebService/">
<SearchResult>
<Status>...</Status>
<Qcountry>aeCountryBE</Qcountry>
<Qservice>aeSrvStandard</Qservice>
<QName>...</QName>
<QCity>bruxelles</QCity>
<QZip />
<QXCoord>0</QXCoord>
<QYCoord>0</QYCoord>
<QRange>0</QRange>
<QPageStep>5</QPageStep>
<QLanguage>aeLangFrench</QLanguage>
<Result>
<NumRecs>11</NumRecs>
<collRecord>
<CRecord>
<Name>...</Name>
<Address>...</Address>
<City>Bruxelles / Brussel</City>
<Zip>1000</Zip>
<Phone>...</Phone>
<Fax> </Fax>
<XCoord>...</XCoord>
<YCoord>...</YCoord>
</CRecord>
<CRecord>
...
</CRecord>
</collRecord>
</Result>
</SearchResult>
</SearchResponse>
</soap:Body>
</soap:Envelope>The listing above shows that all the fields we need are located under the tags "CRecord". We must parse all the document and start caching the data in a structure (containing name, address, etc...) once the CRecord tag start. And output these data cached when the CRecord ends.
Now you can create the file named ListInfobelRecord.py, and copy the code below:
Example 4-4. A Python handler for the .NET Infobel web service.
Be sure to install the last version of the PyXml, see PyXml download page.
# infobel sax parsing handler
from xml.sax import saxutils
# see in bold all the steps necessary to
# catch and print a value
class ListInfobelRecord(saxutils.DefaultHandler):
def __init__(self, value):
self.search_value = value
self.flag_value = 0
self.flag_record = 0
# set a flag for this value to 0
self.flag_name = 0
self.flag_address = 0
self.flag_city = 0
self.flag_zip = 0
self.flag_phone = 0
self.flag_fax = 0
self.flag_xcoord = 0
self.flag_ycoord = 0
self.value_found = ""
# initialize a buffer
self.record_name = ""
self.record_address = ""
self.record_city = ""
self.record_zip = ""
self.record_phone = ""
self.record_fax = ""
self.record_xcoord = ""
self.record_ycoord = ""
print "init ok"
def startElement(self, name, attrs):
if name == self.search_value:
self.flag_value = 1
self.value_found = ""
if self.flag_record:
# if tag start: flag
if name == "Name":
self.flag_name = 1
elif name == "Address":
self.flag_address = 1
elif name == "City":
self.flag_city = 1
elif name == "Zip":
self.flag_zip = 1
elif name == "Phone":
self.flag_phone = 1
elif name == "Fax":
self.flag_fax = 1
elif name == "XCoord":
self.flag_xcoord = 1
elif name == "YCoord":
self.flag_ycoord = 1
if name == "CRecord":
# if CRecord start
# reset all the buffer
self.flag_record = 1
self.record_name = ""
self.record_address = ""
self.record_city = ""
self.record_zip = ""
self.record_phone = ""
self.record_fax = ""
self.record_xcoord = ""
self.record_ycoord = ""
#print "start: " + name
def characters(self, ch):
if self.flag_value:
self.value_found =self.value_found + ch
# if flag for this value on
# append all the characters
# in the buffer
elif self.flag_name:
self.record_name = self.record_name + ch
elif self.flag_address:
self.record_address = self.record_address + ch
elif self.flag_city:
self.record_city = self.record_city + ch
elif self.flag_zip:
self.record_zip = self.record_zip + ch
elif self.flag_phone:
self.record_phone = self.record_phone + ch
elif self.flag_fax:
self.record_fax = self.record_fax + ch
elif self.flag_xcoord:
self.record_xcoord = self.record_xcoord + ch
elif self.flag_ycoord:
self.record_ycoord = self.record_ycoord + ch
def endElement(self, name):
if name == self.search_value:
self.flag_value = 0
print "Record found: " + self.value_found
# if end of CRecord
# print
if name == "CRecord":
self.flag_record = 0
print "record: "
print "name: " , self.record_name
print "address: " , self.record_address
print "city: " , self.record_city
print "phone: " , self.record_phone
print "fax: " , self.record_fax
print "xcoord: " , self.record_xcoord
print "ycoord: " , self.record_ycoord
print
# reset the flag for this value
if name == "Name":
self.flag_name = 0
elif name == "Address":
self.flag_address = 0
elif name == "City":
self.flag_city = 0
elif name == "Zip":
self.flag_zip = 0
elif name == "Phone":
self.flag_phone = 0
elif name == "Fax":
self.flag_fax = 0
elif name == "XCoord":
self.flag_xcoord = 0
elif name == "YCoord":
self.flag_ycoord = 0
#print "end: " + name
We are ready to post the SOAP message and parse the response using Sax and the handler we just create: ListInfobelRecord. Follow the example below:
In the next section I will use the DOM to create, at runtime, the SOAP message.
You can find below a more complete example showing how to consume a .NET web service: using DOM to create your SOAP message and using Sax to parse the response.
![]() | ![]() | ![]() |
| Make a SOAP client with Python. | ![]() My home page Index RSS | Python ZSI SOAP client for JWSDP and .NET web service. |