How to parse SOAP XML with Python?
The issue here is dealing with the XML namespaces:
import requests
from xml.etree import ElementTree
response = requests.get('http://www.labs.skanetrafiken.se/v2.2/querystation.asp?inpPointfr=yst')
# define namespace mappings to use as shorthand below
namespaces = {
'soap': 'http://schemas.xmlsoap.org/soap/envelope/',
'a': 'http://www.etis.fskab.se/v1.0/ETISws',
}
dom = ElementTree.fromstring(response.content)
# reference the namespace mappings here by `<name>:`
names = dom.findall(
'./soap:Body'
'/a:GetStartEndPointResponse'
'/a:GetStartEndPointResult'
'/a:StartPoints'
'/a:Point'
'/a:Name',
namespaces,
)
for name in names:
print(name.text)
The namespaces come from the xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
and xmlns="http://www.etis.fskab.se/v1.0/ETISws"
attributes on the Envelope
and GetStartEndPointResponse
nodes respectively.
Keep in mind, a namespace is inherited by all children nodes of a parent even if the namespace isn't explicitly specified on the child's tag as <namespace:tag>
.
Note: I had to use response.content
rather than response.body
.
An old question but worth to mention another option for this task.
I like to use xmltodict
(Github) a lightweight converter of XML
to python dictionary.
Take your soap response in a variable named stack
Parse it with xmltodict.parse
In [48]: stack_d = xmltodict.parse(stack)
Check the result:
In [49]: stack_d
Out[49]:
OrderedDict([('soap:Envelope',
OrderedDict([('@xmlns:soap',
'http://schemas.xmlsoap.org/soap/envelope/'),
('@xmlns:xsd', 'http://www.w3.org/2001/XMLSchema'),
('@xmlns:xsi',
'http://www.w3.org/2001/XMLSchema-instance'),
('soap:Body',
OrderedDict([('GetStartEndPointResponse',
OrderedDict([('@xmlns',
'http://www.etis.fskab.se/v1.0/ETISws'),
('GetStartEndPointResult',
OrderedDict([('Code',
'0'),
('Message',
None),
('StartPoints',
OrderedDict([('Point',
[OrderedDict([('Id',
'545'),
('Name',
'Get Me'),
('Type',
'sometype'),
('X',
'333'),
('Y',
'222')]),
OrderedDict([('Id',
'634'),
('Name',
'Get me too'),
('Type',
'sometype'),
('X',
'555'),
('Y',
'777')])])]))]))]))]))]))])
At this point it become as easy as to browse a python dictionnary
In [50]: stack_d['soap:Envelope']['soap:Body']['GetStartEndPointResponse']['GetStartEndPointResult']['StartPoints']['Point']
Out[50]:
[OrderedDict([('Id', '545'),
('Name', 'Get Me'),
('Type', 'sometype'),
('X', '333'),
('Y', '222')]),
OrderedDict([('Id', '634'),
('Name', 'Get me too'),
('Type', 'sometype'),
('X', '555'),
('Y', '777')])]