.. _binding:
XML binding
===========
model
-----
The :py:func:`paxb.model` decorator is used to describe a mapping of a python class to an xml element.
All encountered class fields are mapped to xml subelements. In the following example ``User`` class
attributes ``name`` and ``surname`` are mapped to the corresponding xml elements. The model:
.. code-block:: python
import paxb as pb
@pb.model
class User:
name = pb.field()
surname = pb.field()
has a complete mapping description for the document
.. code-block:: xml
Alex
Ivanov
By default class name is used as an xml tag name for a mapping. The default behavior can be altered using
decorator ``name`` argument. The ``User`` class can be rewritten as follows:
.. code-block:: python
import paxb as pb
@pb.model(name='user')
class User:
name = pb.field()
surname = pb.field()
.. code-block:: xml
Alex
Ivanov
field
-----
The :py:func:`paxb.field` function describes a mapping of a python class field to an xml subelement.
In the following example fields ``name`` and ``surname`` are mapped to the corresponding xml subelements.
The name of the fields is used as an xml tag name for a mapping.
.. code-block:: python
import paxb as pb
@pb.model
class User:
name = pb.field()
surname = pb.field()
.. code-block:: xml
Alex
Ivanov
Similarly to the :py:func:`paxb.model` decorator the default behavior can be altered using ``name`` argument.
.. code-block:: python
import paxb as pb
@pb.model
class User:
name = pb.field(name="Name")
surname = pb.field(name="Surname")
.. code-block:: xml
Alex
Ivanov
attribute
---------
The :py:func:`paxb.attr` function describes a mapping of a python class field to an xml element attribute.
In the following example fields ``name`` and ``surname`` are mapped to the corresponding ``User`` element
attributes. The name of the fields is used as an xml tag name for a mapping.
.. code-block:: python
import paxb as pb
@pb.model
class User:
name = pb.attr()
surname = pb.attr()
.. code-block:: xml
Similarly to the :py:func:`paxb.field` function the default behavior can be altered using ``name`` argument.
.. code-block:: python
import paxb as pb
@pb.model
class User:
name = pb.attribute(name="Name")
surname = pb.attribute(name="Surname")
.. code-block:: xml
nested
------
The :py:func:`paxb.nested` function is used to describe a mapping of a python class to an xml element. It is
similar to the :py:func:`paxb.model` decorator, but declares a nested one. Beyond that it acts the same.
The following example illustrates using nested classes:
.. code-block:: python
imort paxb as pb
@pb.model
class Passport:
series = pb.attribute()
number = pb.attribute()
@pb.model
class User:
name = pb.attribute()
surname = pb.attribute()
passport = pb.nested(Passport)
.. code-block:: xml
as_list
-------
The :py:func:`paxb.as_list` function describes a mapping of a python class field to xml subelements.
The corresponding subelements will be deserialized to a list. An element of a list can be field,
nested class or wrapper (will be described later). Look at the example:
.. code-block:: python
import paxb as pb
@pb.model
class User:
emails = pb.as_list(pb.field(name="Email"))
.. code-block:: xml
alex@mail.ru
alex@gmail.com
alex@yandex.ru
wrapper
-------
It is common when a mapped element is placed in a subelement but declaring a nested class is redundant.
Here the :py:func:`paxb.wrapper` function comes forward. Let's look at the example:
.. code-block:: python
import paxb as pb
@pb.model
class User:
email = pb.wrapper('contacts', pb.field())
.. code-block:: xml
alex@gmail.com
Here ``email`` is a direct field of the ``User`` class but in the xml tree it is placed in ``contacts`` subelement.
One :py:func:`paxb.wrapper` can be can be wrapped by another:
.. code-block:: python
import paxb as pb
@pb.model
class User:
email = pb.wrapper('info', pb.wrapper('contacts', pb.field()))
...
.. code-block:: xml
alex@gmail.com
A path can be used instead of a tag name. The following model is equivalent to the former one:
.. code-block:: python
import paxb as pb
@pb.model
class User:
email = pb.wrapper('info/contacts', pb.field())
let's put it all together
-------------------------
All the functions can be mixed together. Look at the more advanced example:
.. code-block:: xml
+79204563539
alex@gmail.com
alex@mail.ru
Moscow
8854
Yekaterinburg
7742
.. code-block:: python
import paxb as pb
@pb.model(name='occupation')
class Occupation:
title = pb.attribute()
address = pb.field()
employees = pb.field()
@pb.model(name='user')
class User:
name = pb.attribute()
surname = pb.attribute()
age = pb.attribute()
phone = pb.wrap('contacts', pb.field())
emails = pb.wrap('contacts', pb.as_list(pb.field(name='email')))
passport_series = pb.wrap('documents/passport', pb.attribute('series'))
passport_number = pb.wrap('documents/passport', pb.attribute('number'))
occupations = pb.wrap('occupations', pb.lst(pb.nested(Occupation)))