Most of the times you need to pass nested data to the soap client. These Complex types can be retrieved using the :meth:`client.get_type` method.
from zeep import Client
client = Client('http://my-enterprise-endpoint.com')
order_type = client.get_type('ns0:Order')
order = order_type(number='1234', price=99)
client.service.submit_order(user_id=1, order=order)However instead of creating an object from a type defined in the XSD you can also pass in a dictionary. Zeep will automatically convert this dict to the required object (and nested child objects) during the call.
from zeep import Client
client = Client('http://my-enterprise-endpoint.com')
client.service.submit_order(user_id=1, order={
'number': '1234',
'price': 99,
})When you need to create multiple types the :meth:`Client.get_type()` calls to retrieve the type class and then instantiating them can be a bit verbose. To simplify this you can use a factory object.
from zeep import Client
client = Client('http://my-enterprise-endpoint.com')
factory = client.type_factory('ns0')
user = factory.User(id=1, name='John')
order = factory.Order(number='1234', price=99)
client.service.submit_order(user=user, order=order).. versionadded:: 0.22
Mapping the semantics of xsd:choice elements to code is unfortunately pretty difficult. Zeep tries to solve this using two methods:
- Accepting the elements in the xsd:choice element as kwargs. This only works for simple xsd:choice definitions.
- Using the special kwarg
_value_Nwhere the N is the number of the choice in the parent type. This method allows you to pass a list of dicts (when maxOccurs != 1) or a dict directly.
The following examples should illustrate this better.
<?xml version="1.0"?>
<schema xmlns:tns="http://tests.python-zeep.org/"
targetNamespace="http://tests.python-zeep.org/">
<element name='ElementName'>
<complexType xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<choice>
<element name="item_1" type="string"/>
<element name="item_2" type="string"/>
</choice>
</complexType>
</element>
</schema>element = client.get_element('ns0:ElementName')
obj = element(item_1='foo')<?xml version="1.0"?>
<schema xmlns:tns="http://tests.python-zeep.org/"
targetNamespace="http://tests.python-zeep.org/">
<element name='ElementName'>
<complexType xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<choice maxOccurs="1">
<sequence>
<element name="item_1_a" type="string"/>
<element name="item_1_b" type="string"/>
</sequence>
</choice>
</complexType>
</element>
</schema>element = client.get_element('ns0:ElementName')
obj = element(_value_1={'item_1_a': 'foo', 'item_1_b': 'bar'})<?xml version="1.0"?>
<schema xmlns:tns="http://tests.python-zeep.org/"
targetNamespace="http://tests.python-zeep.org/">
<element name='ElementName'>
<complexType xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<choice maxOccurs="unbounded">
<element name="item_1" type="string"/>
<element name="item_2" type="string"/>
</choice>
</complexType>
</element>
</schema>element = client.get_element('ns0:ElementName')
obj = element(_value_1=[{'item_1': 'foo'}, {'item_2': 'bar'}])Zeep offers full support for xsd:any elements. xsd:any elements are used as a kind of wildcard and basically allows any element to be used. Zeep needs to know the element name you want to serialize, so the value needs to be wrapped in a special object. This is the :class:`~zeep.xsd.AnyObject`. It takes two parameters, the xsd Element first and the value as the second arg.
from zeep import Client
from zeep import xsd
client = Client('http://my-entrprisy-endpoint.com')
order_type = client.get_element('ns0:Order')
order = xsd.AnyObject(
order_type, order_type(number='1234', price=99))
client.service.submit_something(user_id=1, _value_1=order)xsd:anyType is used as a wildcard type. Where the xsd:Any element allows any element the xsd:anyType allows any type for a specific element. The usage from zeep is almost the same. Instead of passing an :class:`~zeep.xsd.Element` class to the AnyObject an xsd type is passed.
from zeep import Client
from zeep import xsd
client = Client('http://my-entrprisy-endpoint.com')
value = xsd.AnyObject(xsd.String(), 'foobar')
client.service.submit_something(user_id=1, my_string=value)Zeep will automatically validate that all the required values are set when calling an operation. If you want to force a value to be ignored and left out of the generated XML then you can assign the :const:`zeep.xsd.SkipValue` constant.
from zeep import Client
from zeep import xsd
client = Client('http://my-entrprisy-endpoint.com')
client.service.submit_something(user_id=1, my_string=xsd.SkipValue)