Reputation: 53843
I'm trying to get relevant information from a SOAP service from the Dutch government land register (WSDL here) with PySimpleSoap. So far I managed to connect and request information about a specific property with the following code:
from pysimplesoap.client import SoapClient
client = SoapClient(wsdl='http://www1.kadaster.nl/1/schemas/kik-inzage/20141101/verzoekTotInformatie-2.1.wsdl', username='xxx', password='xxx', trace=True)
response = client.VerzoekTotInformatie(
Aanvraag={
'berichtversie': '4.7', # Refers to the schema version
'klantReferentie': klantReferentie, # A reference we can set ourselves.
'productAanduiding': '1185', # a four-digit code referring to whether the response should be in "XML" (1185), "PDF" (1191) or "XML and PDF" (1057).
'Ingang': {
'Object': {
'IMKAD_KadastraleAanduiding': {
'gemeente': 'ARNHEM AC', # municipality
'sectie': 'AC', # section code
'perceelnummer': '1234' # Lot number
}
}
}
}
)
This "kinda" works. I set trace=True
so I get extensive log messages, and in those log messages I see a humongous xml output (paste here) which pretty much includes all info which I request. BUT, I also get this traceback:
Traceback (most recent call last):
File "<input>", line 1, in <module>
'perceelnummer': perceelnummer
File "/Library/Python/2.7/site-packages/pysimplesoap/client.py", line 181, in <lambda>
return lambda *args, **kwargs: self.wsdl_call(attr, *args, **kwargs)
File "/Library/Python/2.7/site-packages/pysimplesoap/client.py", line 346, in wsdl_call
return self.wsdl_call_with_args(method, args, kwargs)
File "/Library/Python/2.7/site-packages/pysimplesoap/client.py", line 372, in wsdl_call_with_args
resp = response('Body', ns=soap_uri).children().unmarshall(output)
File "/Library/Python/2.7/site-packages/pysimplesoap/simplexml.py", line 433, in unmarshall
value = children and children.unmarshall(fn, strict)
File "/Library/Python/2.7/site-packages/pysimplesoap/simplexml.py", line 433, in unmarshall
value = children and children.unmarshall(fn, strict)
File "/Library/Python/2.7/site-packages/pysimplesoap/simplexml.py", line 433, in unmarshall
value = children and children.unmarshall(fn, strict)
File "/Library/Python/2.7/site-packages/pysimplesoap/simplexml.py", line 380, in unmarshall
raise TypeError("Tag: %s invalid (type not found)" % (name,))
TypeError: Tag: IMKAD_Perceel invalid (type not found)
As far as I understand, this means that the IMKAD_Perceel
tag cannot be understood by the simplexml parser which (I'm guessing) is because it could not read/find the definition of this tag in the wdsl file.
So I checked the (enormous amount of) log messages from parsing the wsdl file, and that shows these lines:
DEBUG:pysimplesoap.helpers:Parsing Element element: IMKAD_Perceel
DEBUG:pysimplesoap.helpers:Processing element IMKAD_Perceel element
DEBUG:pysimplesoap.helpers:IMKAD_Perceel has no children!
DEBUG:pysimplesoap.helpers:complexContent/simpleType/element IMKAD_Perceel = IMKAD_Perceel
DEBUG:pysimplesoap.helpers:Parsing Element complexType: IMKAD_Perceel
DEBUG:pysimplesoap.helpers:Processing element IMKAD_Perceel complexType
DEBUG:pysimplesoap.helpers:complexContent/simpleType/element IMKAD_Perceel = IMKAD_OnroerendeZaak
DEBUG:pysimplesoap.helpers:Processing element IMKAD_Perceel complexType
I guess these lines mean that the IMKAD_Perceel
definition is empty. So I used SoapUI to introspect the WSDL file, in which I found an url to this .xsd-file in which I find a definition of the IMKAD_Perceel
:
<xs:element name="IMKAD_Perceel"
substitutionGroup="ipkbo:IMKAD_OnroerendeZaak"
type="ipkbo:IMKAD_Perceel"
/>
The tag indeed seems to be closing itself, which means it is empty. Is this the reason that pysimplesoap thinks that IMKAD_Perceel
is not defined? Why can't it simply interpret the xml and return it back as a dict? (as said before, the full xml output I receive is in this paste).
Does anybody know how I can make pysimplesoap interpret the xml and convert it to a dict, regardless whether it adheres to the wsdl?
All tips are welcome!
Upvotes: 8
Views: 2031
Reputation: 16770
It seems that pysimplesoap
is not capable of dealing with substitutionGroup
in xml schema.
You can see that in the xsd file:
<xs:element name="IMKAD_Perceel"
substitutionGroup="ipkbo:IMKAD_OnroerendeZaak"
type="ipkbo:IMKAD_Perceel"
/>
There is this substitutionGroup
, which means that IMKAD_Perceel
and IMKAD_OnroerendeZaak
is the same thing and substitutable for each other.
In the soap schema, this particular part of response is defined as:
<xs:complexType name="BerichtGegevens">
<xs:annotation>
<xs:documentation>Inhoud van het bericht.</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element ref="ipkbo:IMKAD_OnroerendeZaak" minOccurs="1" maxOccurs="1"/>
<xs:element ref="ipkbo:Recht" minOccurs="1" maxOccurs="1"/><xs:element ref="ipkbo:IMKAD_Stuk" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="ipkbo:IMKAD_Persoon" minOccurs="1" maxOccurs="unbounded"/>
<xs:element ref="ipkbo:GemeentelijkeRegistratie" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
However, you can see the actual response is like:
<ipkbo:BerichtGegevens>
<ipkbo:IMKAD_Perceel>...</ipkbo:IMKAD_Perceel>
<ipkbo:Recht>...</ipkbo:Recht>
<ipkbo:IMKAD_AangebodenStuk>...</ipkbo:IMKAD_AangebodenStuk>
<ipkbo:IMKAD_Persoon>...</ipkbo:IMKAD_Persoon>
</ipkbo:BerichtGegevens>
Then pysimplesoap
seems to get confused and fail to get correct type of response.
Upvotes: 1