Objectif: Obtenir les valeurs dans les balises <Name>
et les imprimer. XML simplifié ci-dessous.
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope 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>
<GetStartEndPointResponse xmlns="http://www.etis.fskab.se/v1.0/ETISws">
<GetStartEndPointResult>
<Code>0</Code>
<Message />
<StartPoints>
<Point>
<Id>545</Id>
<Name>Get Me</Name>
<Type>sometype</Type>
<X>333</X>
<Y>222</Y>
</Point>
<Point>
<Id>634</Id>
<Name>Get me too</Name>
<Type>sometype</Type>
<X>555</X>
<Y>777</Y>
</Point>
</StartPoints>
</GetStartEndPointResult>
</GetStartEndPointResponse>
</soap:Body>
</soap:Envelope>
Tentative:
import requests
from xml.etree import ElementTree
response = requests.get('http://www.labs.skanetrafiken.se/v2.2/querystation.asp?inpPointfr=yst')
# XML parsing here
dom = ElementTree.fromstring(response.text)
names = dom.findall('*/Name')
for name in names:
print(name.text)
J'ai lu d'autres personnes recommandant zeep
d'analyser soap xml mais j'ai eu du mal à comprendre.
Le problème ici concerne les espaces de noms XML:
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,
)
print names
for name in names:
print(name.text)
Les espaces de noms proviennent des attributs xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
et xmlns="http://www.etis.fskab.se/v1.0/ETISws"
des nœuds Envelope
et GetStartEndPointResponse
, respectivement.
N'oubliez pas qu'un espace de noms est hérité par tous les nœuds enfants d'un parent, même s'il n'est pas explicitement spécifié dans la balise de l'enfant sous la forme <namespace:tag>
.
Remarque: je devais utiliser response.content
plutôt que response.body
.
Une vieille question, mais il convient de mentionner une autre option pour cette tâche.
J'aime utiliser xmltodict
(Github) un convertisseur léger de XML
en dictionnaire python.
Prenez votre réponse soap dans une variable nommée stack
Analyser avec xmltodict.parse
In [48]: stack_d = xmltodict.parse(stack)
Vérifiez le résultat:
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')])])]))]))]))]))]))])
À ce stade, il devient aussi facile que de parcourir un dictionnaire python
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')])]