UPDATE 05-09-2019: I still haven't been able to fix this, but I least I think I figured out where the problem is coming from. Apparently Zeep isn't able to determine the type for some elements, I imagine that's what's causing the error I described originally:
DEBUG:zeep.xsd.schema:register_element('{http://eur-lex.europa.eu/search}WORK_PART_OF_WORK', <Element(name='WORK_PART_OF_WORK', type=<UnresolvedType(qname='{http://eur-lex.europa.eu/search}Relation')>)>)
This is happening for multiple elements, so my problem now is how to handle these cases. Is there a way to manually define the type for unrecognized elements?
Original post:
I'm working on a web application in Python 3.6 and Flask, where I need to get some data from a web service using a SOAP API. I've installed the Zeep module to do so, but since this is my first time using a SOAP API and Zeep I'm quite lost. As far as I can tell the request is being sent correctly and I am receiving information from the web service in the terminal window, but then I get the following error:
AttributeError: 'str' object has no attribute 'keys'
The below is WSDL I need to use: https://eur-lex.europa.eu/eurlex-ws?wsdl and XML query I'm trying to run, I've tested it in SOAPUI and it works fine:
<soap:Body>
<sear:searchRequest>
<sear:expertQuery>Title~"Decision (EU) 2016/342"</sear:expertQuery>
<sear:page>1</sear:page>
<sear:pageSize>10</sear:pageSize>
<sear:searchLanguage>en</sear:searchLanguage>
</sear:searchRequest>
</soap:Body>
My code in Python is:
history = HistoryPlugin()
client = Client("https://eur-lex.europa.eu/eurlex-ws?wsdl", wsse=UsernameToken("#######","###########"), plugins=[history])
request_data = {
'expertQuery': 'Title~"Decision (EU) 2016/342"',
'page': 1,
'pageSize': 10,
'searchLanguage': 'en'
}
response = client.service.doQuery(**request_data)
In the terminal window I see the request is being sent and data is being received:
DEBUG:zeep.transports:HTTP Post to https://eur-lex.europa.eu/EURLexWebService:
<?xml version='1.0' encoding='utf-8'?>
<soap-env:Envelope xmlns:soap-env="http://www.w3.org/2003/05/soap-envelope"><soap-env:Header><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsse:UsernameToken><wsse:Username>########</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">###########</wsse:Password></wsse:UsernameToken></wsse:Security></soap-env:Header><soap-env:Body><ns0:searchRequest xmlns:ns0="http://eur-lex.europa.eu/search"><ns0:expertQuery>Title~"Decision (EU) 2016/342"</ns0:expertQuery><ns0:page>1</ns0:page><ns0:pageSize>10</ns0:pageSize><ns0:searchLanguage>en</ns0:searchLanguage></ns0:searchRequest></soap-env:Body></soap-env:Envelope>
DEBUG:urllib3.connectionpool:https://eur-lex.europa.eu:443 "POST /EURLexWebService HTTP/1.1" 200 None
DEBUG:zeep.transports:HTTP Response from https://eur-lex.europa.eu/EURLexWebService (status: 200):
<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:S="http://www.w3.org/2003/05/soap-envelope"><env:Header/><S:Body><searchResults xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:searchLayerHelper="xalan//eu.europa.ec.op.searchlayer.domain.util.SearchLayerHelper" xmlns="http://eur-lex.europa.eu/search" xsi:schemaLocation="http://eur-lex.europa.eu/search https://eur-lex.europa.eu/eurlex-ws?xsd=3">
<numhits>1</numhits>
<totalhits>1</totalhits>
<page>1</page>
<language>en</language>
<result>
<reference>eng_cellar:9c53bb30-eb42-11e5-8a81-01aa75ed71a1_en</reference>
<rank>1</rank>
<content>
<NOTICE>
<EXPRESSION>
<EXPRESSION_TITLE>
<VALUE>Council Decision (EU) 2016/342 of 12 February 2016 on the conclusion, on behalf of the Union, of the Stabilisation and Association Agreement between the European Union and the European Atomic Energy Community, of the one part, and Kosovo *, of the other part</VALUE>
</EXPRESSION_TITLE>
<EXPRESSION_USES_LANGUAGE>
<URI>
<IDENTIFIER>ENG</IDENTIFIER>
</URI>
</EXPRESSION_USES_LANGUAGE>
</EXPRESSION>
<WORK>
<ID_CELEX>
<VALUE>32016D0342</VALUE>
</ID_CELEX>
<RESOURCE_LEGAL_IN-FORCE>
<VALUE>true</VALUE>
</RESOURCE_LEGAL_IN-FORCE>
<RESOURCE_LEGAL_PUBLISHED_IN_OFFICIAL-JOURNAL>
<EMBEDDED_NOTICE>
<WORK>
(***SHORTENED BECAUSE THE RESULTS ARE REALLY LONG***)
</URI>
</SAMEAS>
</MANIFESTATION_PART_OF_MANIFESTATION>
</MANIFESTATION>
</EMBEDDED_NOTICE>
</WORK_HAS_EXPRESSION>
</WORK>
</NOTICE>
</content>
</result>
</searchResults></S:Body></S:Envelope>
But then right after I get this list of errors:
127.0.0.1 - - [30/Aug/2019 16:59:31] "GET /test HTTP/1.1" 500 -
INFO:werkzeug:127.0.0.1 - - [30/Aug/2019 16:59:31] "GET /test HTTP/1.1" 500 -
Traceback (most recent call last):
File "/home/luiscosta/.local/lib/python3.6/site-packages/flask/app.py", line 2463, in __call__
return self.wsgi_app(environ, start_response)
File "/home/luiscosta/.local/lib/python3.6/site-packages/flask/app.py", line 2449, in wsgi_app
response = self.handle_exception(e)
File "/home/luiscosta/.local/lib/python3.6/site-packages/flask/app.py", line 1866, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/luiscosta/.local/lib/python3.6/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/luiscosta/.local/lib/python3.6/site-packages/flask/app.py", line 2446, in wsgi_app
response = self.full_dispatch_request()
File "/home/luiscosta/.local/lib/python3.6/site-packages/flask/app.py", line 1951, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/luiscosta/.local/lib/python3.6/site-packages/flask/app.py", line 1820, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/luiscosta/.local/lib/python3.6/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/luiscosta/.local/lib/python3.6/site-packages/flask/app.py", line 1949, in full_dispatch_request
rv = self.dispatch_request()
File "/home/luiscosta/.local/lib/python3.6/site-packages/flask/app.py", line 1935, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/luiscosta/eur-lex/helpers.py", line 38, in decorated_function
return f(*args, **kwargs)
File "/home/luiscosta/eur-lex/application.py", line 128, in test
response = client.service.doQuery(**request_data)
File "/usr/local/lib/python3.6/dist-packages/zeep/proxy.py", line 45, in __call__
kwargs,
File "/usr/local/lib/python3.6/dist-packages/zeep/wsdl/bindings/soap.py", line 130, in send
return self.process_reply(client, operation_obj, response)
File "/usr/local/lib/python3.6/dist-packages/zeep/wsdl/bindings/soap.py", line 197, in process_reply
result = operation.process_reply(doc)
File "/usr/local/lib/python3.6/dist-packages/zeep/wsdl/bindings/soap.py", line 396, in process_reply
return self.output.deserialize(envelope)
File "/usr/local/lib/python3.6/dist-packages/zeep/wsdl/messages/soap.py", line 94, in deserialize
body_result = self._deserialize_body(body)
File "/usr/local/lib/python3.6/dist-packages/zeep/wsdl/messages/soap.py", line 425, in _deserialize_body
result = self.body.parse(xmlelement, self.wsdl.types, context=context)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/element.py", line 130, in parse
schema_type=self.type,
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/types/complex.py", line 194, in parse_xmlelement
elements, schema, name, context=context
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/indicators.py", line 609, in parse_xmlelements
xmlelements, schema, name, context=context
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/element.py", line 176, in parse_xmlelements
item = self.parse(xmlelement, schema, allow_none=True, context=context)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/element.py", line 130, in parse
schema_type=self.type,
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/types/complex.py", line 194, in parse_xmlelement
elements, schema, name, context=context
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/indicators.py", line 609, in parse_xmlelements
xmlelements, schema, name, context=context
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/element.py", line 176, in parse_xmlelements
item = self.parse(xmlelement, schema, allow_none=True, context=context)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/element.py", line 130, in parse
schema_type=self.type,
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/types/complex.py", line 194, in parse_xmlelement
elements, schema, name, context=context
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/indicators.py", line 609, in parse_xmlelements
xmlelements, schema, name, context=context
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/element.py", line 176, in parse_xmlelements
item = self.parse(xmlelement, schema, allow_none=True, context=context)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/element.py", line 130, in parse
schema_type=self.type,
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/types/complex.py", line 194, in parse_xmlelement
elements, schema, name, context=context
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/indicators.py", line 362, in parse_xmlelements
context=context,
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/indicators.py", line 609, in parse_xmlelements
xmlelements, schema, name, context=context
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/element.py", line 176, in parse_xmlelements
item = self.parse(xmlelement, schema, allow_none=True, context=context)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/element.py", line 130, in parse
schema_type=self.type,
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/types/complex.py", line 194, in parse_xmlelement
elements, schema, name, context=context
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/indicators.py", line 609, in parse_xmlelements
xmlelements, schema, name, context=context
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/element.py", line 176, in parse_xmlelements
item = self.parse(xmlelement, schema, allow_none=True, context=context)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/element.py", line 130, in parse
schema_type=self.type,
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/types/complex.py", line 194, in parse_xmlelement
elements, schema, name, context=context
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/indicators.py", line 307, in parse_xmlelements
sub_elements, schema, context=context
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/element.py", line 176, in parse_xmlelements
item = self.parse(xmlelement, schema, allow_none=True, context=context)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/element.py", line 130, in parse
schema_type=self.type,
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/types/complex.py", line 219, in parse_xmlelement
value = self._value_class(**init_kwargs)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/valueobjects.py", line 95, in __init__
items = _process_signature(self._xsd_type, args, kwargs)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/valueobjects.py", line 207, in _process_signature
values = element.parse_kwargs(kwargs, element_name, available_kwargs)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/indicators.py", line 181, in parse_kwargs
value = element.parse_kwargs(item_value, item_name, item_kwargs)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/indicators.py", line 686, in parse_kwargs
available_sub_kwargs = set(sub_kwargs.keys())
AttributeError: 'str' object has no attribute 'keys'
I'm completely lost and don't know how to fix this because I don't understand what the error means and I couldn't find any information online for this specific error in Zeep.
Any ideas?