========== Data Types ========== There is a global converter factory that is used during data binding between python and xml/json documents. The converter ships with multiple adapters and will attempt to convert values according to the provided list of possible types but in case of an error it will fall back to str, even if that means violating the field typing definition. A warning will also be raised in that case. .. code-block:: ConverterWarning: Failed to convert value `a` to one of [] Schema Types Mapping ==================== Below you can find the mapping of data types between python and xml schema. .. include:: data-types-table.rst Working with custom types ========================= If you are working with a type that's not supported or you want to override one of the builtin adapter's behavior you can register you own. .. doctest:: >>> from dataclasses import dataclass, field >>> from xsdata.formats.converter import Converter, converter >>> from xsdata.formats.dataclass.parsers import XmlParser >>> from xsdata.formats.dataclass.serializers import XmlSerializer ... >>> class TheGoodFloat(float): ... pass ... >>> @dataclass ... class Example: ... good: TheGoodFloat = field(metadata=dict(format="{:.2f}")) ... bad: float ... >>> class TheGoodFloatConverter(Converter): ... def deserialize(self, value: str, **kwargs) -> TheGoodFloat: ... return round(TheGoodFloat(value), 1) # Even nicer ... ... def serialize(self, value: TheGoodFloat, **kwargs) -> str: ... if kwargs["format"]: ... return kwargs["format"].format(value) ... return str(value) ... >>> converter.register_converter(TheGoodFloat, TheGoodFloatConverter()) >>> serializer = XmlSerializer() >>> output = serializer.render(Example(TheGoodFloat(10.983263748), -9.9827632)) >>> print(output) 10.98-9.9827632 >>> XmlParser().from_string(output) Example(good=11.0, bad=-9.9827632) Working with date strings ========================= The builtin converter includes adapters for :class:`datetime.time`, :class:`datetime.date` and :class:`datetime.datetime`. Use the field metadata to set the target `format` according to the :ref:`python:strftime-strptime-behavior` .. doctest:: >>> import datetime as dt >>> from dataclasses import dataclass, field >>> from xsdata.formats.dataclass.serializers import XmlSerializer >>> from xsdata.formats.dataclass.serializers.config import SerializerConfig ... >>> @dataclass ... class Dates: ... date: dt.date = field(metadata=dict(format="%d %B %Y")) ... time: dt.time = field(metadata=dict(format="%H:%M")) ... datetime: dt.datetime = field(metadata=dict(format="%d %B %Y %H:%M")) ... >>> obj = Dates( ... date=dt.date(2020, 1, 6), ... time=dt.time(18, 15, 30), ... datetime=dt.datetime(2020, 1, 6, 18, 15, 30) ... ) ... >>> config = SerializerConfig(pretty_print=True) >>> serializer = XmlSerializer(config=config) >>> print(serializer.render(obj)) 06 January 2020 06 January 2020 18:15 Models generated by the cli from a schema definition use the builtin datatypes :class:`~xsdata.models.datatype.XmlDate`, :class:`~xsdata.models.datatype.XmlTime` and :class:`~xsdata.models.datatype.XmlDateTime` instead because the datetime objects don't support all the xml features like years bce. The builtin date types have util methods to convert from and to datetime objects whenever possible. .. doctest:: >>> from dataclasses import dataclass >>> from xsdata.formats.dataclass.serializers import XmlSerializer >>> from xsdata.formats.dataclass.serializers.config import SerializerConfig >>> from xsdata.models.datatype import XmlDate, XmlTime, XmlDateTime ... >>> @dataclass ... class Dates: ... date: XmlDate ... time: XmlTime ... datetime: XmlDateTime ... >>> obj = Dates( ... date=XmlDate(2020, 1, 6, 120), ... time=XmlTime(18, 15, 30, 123000, 0), ... datetime=XmlDateTime(2020, 1, 6, 18, 15, 30) ... ) ... >>> config = SerializerConfig(pretty_print=True) >>> serializer = XmlSerializer(config=config) >>> print(serializer.render(obj)) 2020-01-06+02:00 2020-01-06T18:15:30 Working with binary data ======================== xs:hexBinary and xs:base64Binary types are mapped to python :class:`bytes` and are encoded/decoded with :mod:`python:binascii` and :mod:`python:base64` modules. .. doctest:: >>> from dataclasses import dataclass, field >>> from xsdata.formats.dataclass.serializers import XmlSerializer >>> from xsdata.formats.dataclass.serializers.config import SerializerConfig ... >>> @dataclass ... class Binary: ... base_16: bytes = field(metadata=dict(format="base16")) ... base_64: bytes = field(metadata=dict(format="base64")) ... >>> obj = Binary( ... base_16="xml".encode(), ... base_64="binding".encode(), ... ) ... >>> config = SerializerConfig(pretty_print=True) >>> serializer = XmlSerializer(config=config) >>> print(serializer.render(obj)) 786D6C YmluZGluZw==