Wrapper#

Some XML documents have deep element hierarchy which requires to declare a lot of “dumb” sub-models to extract the deepest element data. pydantic_xml.wrapped() helps to get rid of that boilerplate code.

Wrapped entities#

To declare a field bound to a sub-element text, attribute or element mark that field as pydantic_xml.wrapped() providing it with the sub-element path and the entity type. It can be applied to a primitive type, model, mapping or collection as well.

Model
class Company(BaseXmlModel):
    city: str = wrapped(
        'Info/Headquarters/Location',
        element(tag='City'),
    )
    country: str = wrapped(
        'Info/Headquarters/Location/Country',
    )
Document
<Company>
    <Info>
        <Headquarters>
            <Location>
                <City>Hawthorne</City>
                <Country>US</Country>
            </Location>
        </Headquarters>
    </Info>
</Company>
{
    "country": "US",
    "city": "Hawthorne"
}

Nested wrappers#

Wrapper can be wrapped by another wrapper building up a nested structure. It helps to extract data from sub-elements from different namespaces:

Model
class Company(
    BaseXmlModel,
    ns='co',
    nsmap={'co': 'http://company.org/co'},
):
    city: constr(strip_whitespace=True) = wrapped(
        'Info',
        ns='co',
        entity=wrapped(
            'Headquarters/Location',
            ns='hq',
            nsmap={'hq': 'http://company.org/hq'},
            entity=element(
                tag='City',
                ns='loc',
                nsmap={'loc': 'http://company.org/loc'},
            ),
        ),
    )
Document
<co:Company xmlns:co="http://company.org/co">
    <co:Info>
        <hq:Headquarters xmlns:hq="http://company.org/hq">
            <hq:Location>
                <loc:City xmlns:loc="http://company.org/loc">
                    Hawthorne
                </loc:City>
            </hq:Location>
        </hq:Headquarters>
    </co:Info>
</co:Company>
{
    "country": "US",
    "city": "Hawthorne"
}