Homogeneous collections#

Homogeneous collection is a collection of same type elements. The most common homogeneous collections are typing.List, typing.Set and variable-length tuple typing.Tuple (like Tuple[int, ...])

Primitive homogeneous collection#

A field of a primitive homogeneous collection type marked as pydantic_xml.element() is bound to the sub-elements texts.

Model
class Company(BaseXmlModel):
    products: List[str] = element(tag='Product')
Document
<Company>
    <Product>Several launch vehicles</Product>
    <Product>Starlink</Product>
    <Product>Starship</Product>
</Company>
{
    "products": [
        "Several launch vehicles",
        "Starlink",
        "Starship"
    ]
}

Model homogeneous collection#

A field of a model homogeneous collection type is bound to sub-elements. Then the sub-element is used as the root for that sub-model. For more information see model data binding. The tag parameter is used to declare sub-elements tag to which the sub-models are bound. If it is omitted the sub-model tag parameter is used. If it is omitted too field name is used (respecting pydantic field aliases).

Model
class Social(BaseXmlModel):
    type: str = attr()
    url: str


class Product(BaseXmlModel):
    status: Literal['running', 'development'] = attr()
    launched: Optional[int] = attr(default=None)
    title: str


class Company(BaseXmlModel):
    socials: Tuple[Social, ...] = element(tag='social')
    products: List[Product] = element(tag='product')
Document
<Company>
    <social type="linkedin">https://www.linkedin.com/company/spacex</social>
    <social type="twitter">https://twitter.com/spacex</social>
    <social type="youtube">https://www.youtube.com/spacex</social>

    <product status="running" launched="2013">Several launch vehicles</product>
    <product status="running" launched="2019">Starlink</product>
    <product status="development">Starship</product>
</Company>
{
    "socials": [
        {
            "type": "linkedin",
            "url": "https://www.linkedin.com/company/spacex"
        },
        {
            "type": "twitter",
            "url": "https://twitter.com/spacex"
        },
        {
            "type": "youtube",
            "url": "https://www.youtube.com/spacex"
        }
    ],
    "products": [
        {
            "status": "running",
            "launched": 2013,
            "title": "Several launch vehicles"
        },
        {
            "status": "running",
            "launched": 2019,
            "title": "Starlink"
        },
        {
            "status": "development",
            "title": "Starship"
        }
    ]
}

Dict homogeneous collection#

A field of a mapping homogeneous collection type is bound to sub-elements attributes:

Model
class Company(BaseXmlModel):
    products: List[Dict[str, str]] = element(tag='product')
Document
<Company>
    <product status="running" launched="2013"/>
    <product status="running" launched="2019"/>
    <product status="development"/>
</Company>
{
    "products": [
        {
            "status": "running",
            "launched": "2013"
        },
        {
            "status": "running",
            "launched": "2019"
        },
        {
            "status": "development"
        }
    ]
}

Adjacent sub-elements#

Some xml documents contain a list of adjacent elements related to each other. To group such elements a homogeneous collection of heterogeneous ones may be used:

Model
class Products(RootXmlModel):
    root: List[Tuple[str, Optional[int]]] = element(tag='info')
Document
<Products>
    <info type="status">running</info>
    <info type="launched">2013</info>
    <info type="status">running</info>
    <info type="launched">2019</info>
    <info type="status">development</info>
    <info type="launched"></info>
</Products>
[
    [
        "running",
        2013
    ],
    [
        "running",
        2019
    ],
    [
        "development",
        null
    ]
]

To group sub-elements with different tags it is necessary to declare a sub-model for each one:

Model
class Product(BaseXmlModel, tag='product'):
    status: str = attr()
    title: str


class Launch(RootXmlModel[int], tag='launched'):
    pass


class Products(RootXmlModel):
    root: List[Tuple[Product, Optional[Launch]]]
Document
<Products>
    <product status="running">Several launch vehicles</product>
    <launched>2013</launched>
    <product status="running">Starlink</product>
    <launched>2019</launched>
    <product status="development">Starship</product>
</Products>
[
    [
        {
            "title": "Several launch vehicles",
            "status": "running"
        },
        2013
    ],
    [
        {
            "title": "Starlink",
            "status": "running"
        },
        2019
    ],
    [
        {
            "title": "Starship",
            "status": "development"
        },
        null
    ]
]