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!
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.