### Install pydantic-xml using pip
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/installation.md
Use this command to install the base pydantic-xml library.
```bash
pip install pydantic-xml
```
--------------------------------
### Install Development Dependencies
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/contribute.md
Run this command to install all development dependencies for the project, excluding the root package itself.
```console
$ poetry install --no-root
```
--------------------------------
### Install Documentation Dependencies
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/contribute.md
Install the necessary dependencies to build the project's documentation. The '-E docs' flag enables the 'docs' extra.
```console
$ poetry install -E docs
```
--------------------------------
### Install Pre-commit Hooks
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/contribute.md
Install pre-commit hooks to automatically check code style before each commit. This ensures adherence to project coding conventions.
```console
$ pre-commit install
```
--------------------------------
### Example XML Document
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/misc.md
This XML document serves as the expected output for the `Request` model with computed fields.
```xml
150.172.238.178150.172.230.21**********
```
--------------------------------
### Example HTML Document with DTD
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/misc.md
An example of an HTML document generated with a Document Type Declaration, showcasing the structure and content.
```xml
This is a title
Hello world!
```
--------------------------------
### Install pydantic-xml with lxml support
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/installation.md
Install pydantic-xml with the optional lxml dependency for enhanced XML serialization. This is recommended if you need to use lxml as your XML backend.
```bash
pip install pydantic-xml[lxml]
```
--------------------------------
### Build Documentation
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/contribute.md
Navigate to the docs directory and run 'make html' to build the HTML version of the documentation. Ensure documentation dependencies are installed first.
```console
cd docs
make html
```
--------------------------------
### XML Representation of Model Unions
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/unions.md
Example XML structure showing a log containing different types of events (mouse and keyboard).
```xml
CTRLC
```
--------------------------------
### Input XML for Raw Fields
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/raw.md
Example XML demonstrating different ways raw contact elements can be structured, including attributes, nested links, and direct text content.
```xml
https://twitter.com/spacex
https://www.youtube.com/spacex
```
--------------------------------
### Ordered Search Mode Example
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/elements.md
Employ 'ordered' mode when element order is important, but unexpected elements may appear. This mode skips unknown elements during the sequential search.
```python
class Company(
BaseXmlModel,
tag='Company',
search_mode='ordered',
):
founded: str = element(tag='Founded')
website: str = element(tag='WebSite')
```
--------------------------------
### XML for Sub-element Attributes
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/mappings.md
Example XML where a Company element contains a 'Founder' sub-element with 'name' and 'surname' attributes.
```xml
```
--------------------------------
### Ordered Search Mode Warning Example
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/elements.md
Demonstrates a potential pitfall with 'ordered' search mode where duplicate tags can lead to unexpected binding results due to look-ahead behavior.
```python
class Model(BaseXmlModel, search_mode='ordered'):
field1: Optional[str] = element(tag='element1')
field2: str = element(tag='element2')
field3: str = element(tag='element1')
```
```xml
valuevalue
```
--------------------------------
### Unordered Search Mode Example
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/elements.md
Utilize 'unordered' mode when the order of elements does not matter. This mode searches for fields among all sub-elements regardless of their position.
```python
class Company(
BaseXmlModel,
tag='Company',
search_mode='unordered',
):
founded: str = element(tag='Founded')
website: str = element(tag='WebSite')
```
--------------------------------
### XML for TypedDict Attributes
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/mappings.md
Example XML where a Company element has attributes like 'founded', 'employees', and 'website' directly bound from a TypedDict.
```xml
```
--------------------------------
### XML Representation of Discriminated Union
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/unions.md
Example XML showing a 'hardware' element containing a 'device' with a 'type' attribute that discriminates between CPU and GPU.
```xml
4096
```
--------------------------------
### Example XML Document Structure
Source: https://github.com/dapper91/pydantic-xml/blob/master/README.rst
This XML structure corresponds to the `Company` model defined above, demonstrating how attributes and nested elements are represented.
```xml
https://www.spacex.comSeveral launch vehiclesStarlinkStarship
```
--------------------------------
### XML Representation of Primitive Unions
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/unions.md
Example XML structure demonstrating how messages with float or datetime timestamps are represented.
```xml
hello world
```
--------------------------------
### JSON Representation of Model Unions
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/unions.md
Example JSON structure corresponding to the XML log with mixed event types.
```json
{
"events": [
{
"timestamp": 1674999183.5486422,
"position": {"x": 234, "y": 345}
},
{
"timestamp": 1674999184.227246,
"type": "KEYDOWN",
"key": "CTRL"
},
{
"timestamp": 1674999185.6342669,
"type": "KEYDOWN",
"key": "C"
},
{
"timestamp": 1674999186.270716,
"position": {"x": 236, "y": 211}
}
]
}
```
--------------------------------
### XML for Local Element Attributes
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/mappings.md
Example XML structure where a Company element has 'trade-name' and 'type' as local attributes.
```xml
```
--------------------------------
### XML Document Example
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/quickstart.md
This XML document demonstrates various pydantic-xml features including attributes, elements, nested structures, namespaces, and wrapped fields.
```xml
2002-03-1412000https://www.spacex.comspacecommunicationsUSCaliforniaHawthornehttps://www.linkedin.com/company/spacexhttps://twitter.com/spacexhttps://www.youtube.com/spacexSeveral launch vehiclesStarlinkStarship
```
--------------------------------
### Example XML Structure for Company and Products
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/index.md
This XML snippet illustrates the structure of a 'Company' document, including its 'trade-name' attribute, 'website' element, and a list of 'product' elements, each with its own attributes and text content. This structure corresponds to the pydantic models defined previously.
```xml
https://www.spacex.comSeveral launch vehiclesStarlinkStarship
```
--------------------------------
### Strict Search Mode Example
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/elements.md
Use 'strict' mode for precise document validation where element order and presence are critical. This mode is efficient for large documents as it avoids look-ahead operations.
```python
class Company(
BaseXmlModel,
tag='Company',
search_mode='strict',
):
founded: str = element(tag='Founded')
website: str = element(tag='WebSite')
```
--------------------------------
### JSON Example of Homogeneous Data
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/homogeneous.md
This JSON structure represents a list of launch vehicles, where each inner list contains an object with vehicle details and a year. It demonstrates a common pattern for homogeneous data representation.
```json
[
[
{
"title": "Several launch vehicles",
"status": "running"
},
2013
],
[
{
"title": "Starlink",
"status": "running"
},
2019
],
[
{
"title": "Starship",
"status": "development"
},
null
]
]
```
--------------------------------
### JSON Representation of Primitive Unions
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/unions.md
Example JSON structure corresponding to the XML representation of messages with union types.
```json
{
"messages": [
{
"timestamp": 1674995230.295639,
"text": "hello world"
},
{
"timestamp": "2023-01-29T17:30:38.762166"
}
]
}
```
--------------------------------
### JSON Representation of Discriminated Union
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/unions.md
Example JSON corresponding to the XML discriminated union, showing the resolved sub-model type and its fields.
```json
{
"accelerator": {
"type": "GPU",
"cores": 4096,
"cuda": false
}
}
```
--------------------------------
### Custom None Encoding with PlainSerializer
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/misc.md
Define a custom encoding for `None` values in XML using `PlainSerializer` and `BeforeValidator`. This example encodes `None` as the string 'null' and decodes 'null' back to `None`.
```python
from typing import Annotated, Optional, TypeVar
from xml.etree.ElementTree import canonicalize
from pydantic import BeforeValidator, PlainSerializer
from pydantic_xml import BaseXmlModel, element
InnerType = TypeVar('InnerType')
XmlOptional = Annotated[
Optional[InnerType],
PlainSerializer(lambda val: val if val is not None else 'null'),
BeforeValidator(lambda val: val if val != 'null' else None),
]
class Company(BaseXmlModel):
title: XmlOptional[str] = element(default=None)
xml_doc = '''
null
'''
company = Company.from_xml(xml_doc)
assert company.title is None
assert canonicalize(company.to_xml(), strip_text=True) == canonicalize(xml_doc, strip_text=True)
```
--------------------------------
### Serialize xs:list with xml_field_serializer
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/misc.md
Use the `xml_field_serializer` decorator to define custom serialization logic for fields, such as space-separated lists. This example demonstrates serializing lists of floats into a space-separated string within an XML element.
```python
import pathlib
from typing import List
from xml.etree.ElementTree import canonicalize
from pydantic_xml import BaseXmlModel, element, xml_field_serializer, xml_field_validator
from pydantic_xml.element import XmlElementReader, XmlElementWriter
class Plot(BaseXmlModel):
x: List[float] = element()
y: List[float] = element()
@xml_field_validator('x', 'y')
@classmethod
def validate_space_separated_list(cls, element: XmlElementReader, field_name: str) -> List[float]:
if (sub_element := element.pop_element(field_name, search_mode=cls.__xml_search_mode__)) and (
text := sub_element.pop_text()
):
return list(map(float, text.split()))
return []
@xml_field_serializer('x', 'y')
def serialize_space_separated_list(self, element: XmlElementWriter, value: List[float], field_name: str) -> None:
sub_element = element.make_element(tag=field_name, nsmap=None)
sub_element.set_text(' '.join(map(str, value)))
element.append_element(sub_element)
xml_doc = pathlib.Path('./doc.xml').read_text()
plot = Plot.from_xml(xml_doc)
assert canonicalize(plot.to_xml(), strip_text=True) == canonicalize(xml_doc, strip_text=True)
```
```xml
0.0 1.0 2.0 3.0 4.0 5.00.0 3.2 5.4 4.1 2.0 -1.2
```
--------------------------------
### Pydantic-XML Model Definition
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/quickstart.md
This Python code defines Pydantic models for parsing the example XML. It includes various field types like attributes, elements, wrapped fields, enums, and custom validators, along with namespace handling.
```python
import pathlib
from datetime import date
from enum import Enum
from typing import Dict, List, Literal, Optional, Set, Tuple
import pydantic as pd
from pydantic import HttpUrl, conint
from pydantic_xml import BaseXmlModel, RootXmlModel, attr, element, wrapped
NSMAP = {
'co': 'http://www.company.com/contact',
'hq': 'http://www.company.com/hq',
'pd': 'http://www.company.com/prod',
}
class Headquarters(BaseXmlModel, ns='hq', nsmap=NSMAP):
country: str = element()
state: str = element()
city: str = element()
@pd.field_validator('country')
def validate_country(cls, value: str) -> str:
if len(value) > 2:
raise ValueError('country must be of 2 characters')
return value
class Industries(RootXmlModel):
root: Set[str] = element(tag='Industry')
class Social(BaseXmlModel, ns_attrs=True, ns='co', nsmap=NSMAP):
type: str = attr()
url: HttpUrl
class Product(BaseXmlModel, ns_attrs=True, ns='pd', nsmap=NSMAP):
status: Literal['running', 'development'] = attr()
launched: Optional[int] = attr(default=None)
title: str
class Person(BaseXmlModel):
name: str = attr()
class CEO(Person):
position: Literal['CEO'] = attr()
class CTO(Person):
position: Literal['CTO'] = attr()
class COO(Person):
position: Literal['COO'] = attr()
class Company(BaseXmlModel, tag='Company', nsmap=NSMAP):
class CompanyType(str, Enum):
PRIVATE = 'Private'
PUBLIC = 'Public'
trade_name: str = attr(name='trade-name')
type: CompanyType = attr()
founder: Dict[str, str] = element(tag='Founder')
founded: Optional[date] = element(tag='Founded')
employees: conint(gt=0) = element(tag='Employees')
website: HttpUrl = element(tag='WebSite')
industries: Industries = element(tag='Industries')
key_people: Tuple[CEO, CTO, COO] = wrapped('key-people', element(tag='person'))
headquarters: Headquarters
socials: List[Social] = wrapped(
'contacts/socials',
element(tag='social', default_factory=list),
ns='co',
nsmap=NSMAP,
)
products: Tuple[Product, ...] = element(tag='product', ns='pd')
xml_doc = pathlib.Path('./doc.xml').read_text()
company = Company.from_xml(xml_doc)
json_doc = pathlib.Path('./doc.json').read_text()
assert company == Company.model_validate_json(json_doc)
```
--------------------------------
### XML Serialization with Custom Parameters
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/misc.md
Customize XML serialization using parameters like pretty_print and encoding. Pass these as extra arguments to the to_xml() method.
```python
xml = obj.to_xml(
pretty_print=True,
encoding='UTF-8',
standalone=True
)
print(xml)
```
--------------------------------
### Dynamic Model Creation
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/misc.md
Create Pydantic models on the fly using runtime information for field definitions. The field specification syntax is similar to Pydantic's.
```python
Company = create_model(
'Company',
trade_name=(str, attr(name='trade-name')),
type=(str, attr()),
)
```
--------------------------------
### XML with Default Namespaces
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/misc.md
This XML structure illustrates how default namespaces are applied to elements and their sub-elements, and how nested default namespaces can override parent namespaces.
```xml
https://www.linkedin.com/company/spacexhttps://twitter.com/spacexhttps://www.youtube.com/spacex
```
--------------------------------
### Enable Mypy Plugin in pyproject.toml
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/misc.md
Add this configuration to your pyproject.toml file to enable the pydantic-xml mypy plugin.
```toml
[tool.mypy]
plugins = [
"pydantic_xml.mypy"
]
```
--------------------------------
### Enable Mypy Plugin in mypy.ini
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/misc.md
Add this configuration to your mypy.ini file to enable the pydantic-xml mypy plugin.
```ini
[mypy]
plugins = pydantic_xml.mypy
```
--------------------------------
### Output XML from Raw Fields
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/raw.md
The resulting XML after processing the raw fields, showing how different input formats are normalized into a consistent structure.
```xml
https://www.linkedin.com/company/spacexhttps://twitter.com/spacexhttps://www.youtube.com/spacex
```
--------------------------------
### Define Product Model with XML Attributes and Elements
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/index.md
This Python code defines a Product model using pydantic-xml, specifying how its fields map to XML attributes ('status', 'launched') and element text. It demonstrates the use of `attr()` for attributes and basic type hints for element text.
```python
class Product(BaseXmlModel):
status: Literal['running', 'development'] = attr() # extracted from the 'status' attribute
launched: Optional[int] = attr(default=None) # extracted from the 'launched' attribute
title: str # extracted from the element text
```
--------------------------------
### Define Base XML Model
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/quickstart.md
Inherit from `BaseXmlModel` to create models that can be serialized to and deserialized from XML. Use `.to_xml()` for serialization and `.from_xml()` for deserialization.
```python
from pydantic_xml import BaseXmlModel
class Company(BaseXmlModel):
description: constr(strip_whitespace=True)
```
--------------------------------
### Declare Wrapped Fields
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/wrapper.md
Use `pydantic_xml.wrapped()` to bind a field to a sub-element's text, attribute, or element. Provide the sub-element path and the entity type. This example shows binding to a string field using a direct path and an explicit `element` tag.
```python
class Company(BaseXmlModel):
city: str = wrapped(
'Info/Headquarters/Location',
element(tag='City'),
)
country: str = wrapped(
'Info/Headquarters/Location/Country',
)
```
--------------------------------
### Document Type Declaration (DTD) Implementation
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/misc.md
Implement document type declarations for XML models using the lxml backend. This involves subclassing BaseXmlModel and defining DOC_PUBLIC_ID and DOC_SYSTEM_URL.
```python
from typing import Any, ClassVar, Union
import pydantic_xml as pxml
import lxml.etree
class DTDXmlModel(pxml.BaseXmlModel):
DOC_PUBLIC_ID: ClassVar[str]
DOC_SYSTEM_URL: ClassVar[str]
def to_xml(
self,
*,
skip_empty: bool = False,
exclude_none: bool = False,
exclude_unset: bool = False,
**kwargs: Any,
) -> Union[str, bytes]:
root = self.to_xml_tree(skip_empty=skip_empty, exclude_none=exclude_none, exclude_unset=exclude_unset)
tree = lxml.etree.ElementTree(root)
tree.docinfo.public_id = self.DOC_PUBLIC_ID
tree.docinfo.system_url = self.DOC_SYSTEM_URL
return lxml.etree.tostring(tree, **kwargs)
class Html(DTDXmlModel, tag='html'):
DOC_PUBLIC_ID: ClassVar[str] = '-//W3C//DTD HTML 4.01//EN'
DOC_SYSTEM_URL: ClassVar[str] = 'http://www.w3.org/TR/html4/strict.dtd'
title: str = pxml.wrapped('head', pxml.element())
body: str = pxml.element()
html_doc = Html(title="This is a title", body="Hello world!")
xml = html_doc.to_xml(pretty_print=True)
print(xml.decode())
```
--------------------------------
### Ordered Mode XML and JSON Representation
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/elements.md
Shows the XML input and JSON output for a model using the 'ordered' search mode, including an intervening element.
```xml
2002-03-14https://www.spacex.com
```
```json
{
"founded": "2002-03-14",
"website": "https://www.spacex.com"
}
```
--------------------------------
### Declare Element Namespace with `element()`
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/elements.md
Declare the namespace for a sub-element by passing `ns` and `nsmap` parameters to `pydantic_xml.element()`. `ns` is the alias, and `nsmap` is the mapping dictionary.
```python
class Company(BaseXmlModel, tag='company'):
founded: dt.date = element(
ns='co',
nsmap={'co': 'http://www.company.com/co'},
)
website: HttpUrl = element(tag='web-site')
```
--------------------------------
### XML Output of Template Models
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/aliases.md
This XML demonstrates how the `alias_generator` in the template models correctly maps fields to their aliased names in the XML output.
```xml
Coyote V8General Electric PassportV8
```
--------------------------------
### Strict Mode XML and JSON Representation
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/elements.md
Illustrates the XML input and JSON output for a model configured with the 'strict' search mode.
```xml
https://www.spacex.com2002-03-14
```
```json
{}
```
--------------------------------
### Grouping Heterogeneous Sub-elements with Explicit Models
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/homogeneous.md
To group sub-elements with different tags, declare a separate Pydantic-XML model for each tag. Then, use a List of Tuples where each tuple element corresponds to one of these models.
```python
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]]]
```
--------------------------------
### XML Representation of TokenAuth Request
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/generics.md
This XML snippet demonstrates a `request` with a `TokenAuth` structure. The `auth` tag contains a nested `token` element, representing token-based authentication.
```xml
7de9e375-84c1-441f-a628-dbaf5017e94f
```
--------------------------------
### Map Dictionary to Local Element Attributes
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/mappings.md
Use a Dict field to bind to local element attributes. The keys of the dictionary correspond to attribute names.
```python
class Company(BaseXmlModel):
properties: Dict[str, str]
```
--------------------------------
### Define a Root XML Model
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/models.md
Define a root model that binds to the root XML element. The tag name can be specified or inferred from the class name. Parsing errors occur if the element is not found.
```python
class Company(BaseXmlModel, tag='company'):
title: str
```
--------------------------------
### Explicitly Define Namespace for Sub-Models
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/elements.md
When a sub-model shares a namespace with its parent, define the `ns` and `nsmap` explicitly on the sub-model class, as they are not inherited.
```python
from pydantic_xml import BaseXmlModel, element
NSMAP = {
'co': 'http://www.company.com/co',
}
class SubModel(BaseXmlModel, ns='co', nsmap=NSMAP): # define ns and nsmap explicitly
field2: str = element(tag='element1')
class Model(BaseXmlModel, ns='co', nsmap=NSMAP):
field1: str = element(tag='element1') # ns "co" is inherited by the element
sub: SubModel # ns and nsmap are not inherited by the SubModel
model = Model(field1="value1", sub=SubModel(field2="value2"))
print(model.to_xml(pretty_print=True).decode())
```
--------------------------------
### Template Model with Alias Generator
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/aliases.md
Define a base template model and use `model_config` with `alias_generator` to map fields to different names for specific inherited models.
```python
class VehicleTemplate(BaseXmlModel):
drivers: int = attr()
title: str = attr()
engine: str = element()
class Car(VehicleTemplate, tag='car'):
model_config = pd.ConfigDict(
alias_generator=lambda field: {'title': 'make', 'engine': 'motor'}.get(field, field),
)
class Airplane(VehicleTemplate, tag='airplane'):
model_config = pd.ConfigDict(
alias_generator=lambda field: {'drivers': 'pilots', 'title': 'model'}.get(field, field),
)
class Vehicles(BaseXmlModel, tag='vehicles'):
items: List[Union[Car, Airplane]]
```
--------------------------------
### Apply Namespace to Model Fields via `element()`
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/elements.md
Namespaces and mappings can be applied to model types using `pydantic_xml.element()`. If omitted, the model's own namespace and mapping are used.
```python
class Headquarters(
BaseXmlModel,
tag='headquarters',
ns='hq',
nsmap={'hq': 'http://www.company.com/hq'},
):
country: str = element(ns='hq')
state: str = element(ns='hq')
city: str = element(ns='hq')
class Company(BaseXmlModel, tag='company'):
headquarters: Headquarters
```
--------------------------------
### Inherit Model Namespace for Attributes
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/attributes.md
Enable attributes to inherit the model's namespace by setting `ns_attrs=True` and defining the model-level namespace and namespace map.
```python
class Company(
BaseXmlModel,
ns_attrs=True,
ns='co',
nsmap={'co': 'http://company.org/co'},
):
trade_name: str = attr(name='trade-name')
type: str = attr()
```
--------------------------------
### Exclude Empty Entities with skip_empty=True
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/misc.md
Pass `skip_empty=True` to `pydantic_xml.BaseXmlModel.to_xml()` to exclude all empty entities from the resulting XML. This parameter applies to the root model and its sub-models by default but can be adjusted per model.
```python
class Product(BaseXmlModel, tag='Product', skip_empty=True):
status: Optional[Literal['running', 'development']] = attr(default=None)
launched: Optional[int] = attr(default=None)
title: Optional[str] = element(tag='Title', default=None)
class Company(BaseXmlModel, tag='Company'):
trade_name: str = attr(name='trade-name')
website: str = element(tag='WebSite', default='')
products: Tuple[Product, ...] = element()
company = Company(
trade_name="SpaceX",
products=[
Product(status="running", launched=2013, title="Several launch vehicles"),
Product(status="running", title="Starlink"),
Product(status="development"),
Product(),
],
)
```
```xml
Several launch vehiclesStarlink
```
--------------------------------
### Pydantic Models for Default Namespaces
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/misc.md
Define pydantic models that correspond to the XML structure with default namespaces. The `nsmap` parameter with an empty key ('') is used to set the default namespace for a model and its children.
```python
from typing import List
from pydantic_xml import BaseXmlModel, element
class Socials(
BaseXmlModel,
tag='socials',
nsmap={'': 'http://www.company.com/soc'},
):
urls: List[str] = element(tag='social')
class Contacts(
BaseXmlModel,
tag='contacts',
nsmap={'': 'http://www.company.com/cnt'},
):
socials: Socials = element()
class Company(
BaseXmlModel,
tag='company',
nsmap={'': 'http://www.company.com/co'},
):
contacts: Contacts = element()
```
--------------------------------
### Parse XML and Validate with JSON
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/models.md
Read an XML document into a Pydantic model and then validate it against a JSON representation. This showcases bidirectional data handling.
```python
xml_doc = pathlib.Path('./doc.xml').read_text()
directory = Directory.from_xml(xml_doc)
json_doc = pathlib.Path('./doc.json').read_text()
assert directory == Directory.model_validate_json(json_doc)
```
--------------------------------
### Parse XML to Pydantic Model and Serialize to JSON
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/quickstart.md
Use `from_xml` to parse an XML document into a Pydantic model, then use the model's `.json()` method to serialize it to a JSON string. This demonstrates pydantic-xml's capability as an XML-to-JSON transcoder.
```python
xml_doc = pathlib.Path('./doc.xml').read_text()
company = Company.from_xml(xml_doc)
json_doc = pathlib.Path('./doc.json')
json_doc.write_text(company.json(indent=4))
```
--------------------------------
### Unordered Mode XML and JSON Representation
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/elements.md
Presents the XML input and JSON output for a model configured with the 'unordered' search mode.
```xml
https://www.spacex.com2002-03-14
```
```json
{
"founded": "2002-03-14",
"website": "https://www.spacex.com"
}
```
--------------------------------
### Base64 Encoding for Bytes Fields in XML
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/misc.md
Illustrates encoding bytes typed fields as Base64 strings during XML serialization and decoding them back using `@field_validator`. This is useful for embedding binary data within XML.
```python
import base64
import pathlib
from typing import List, Optional, Union
from xml.etree.ElementTree import canonicalize
from pydantic import field_serializer, field_validator
from pydantic_xml import BaseXmlModel, RootXmlModel, attr, element
class File(BaseXmlModel):
name: str = attr()
content: bytes = element()
@field_serializer('content')
def encode_content(self, value: bytes) -> str:
return base64.b64encode(value).decode()
@field_validator('content', mode='before')
def decode_content(cls, value: Optional[Union[str, bytes]]) -> Optional[bytes]:
if isinstance(value, str):
return base64.b64decode(value)
return value
class Files(RootXmlModel, tag='files'):
root: List[File] = element(tag='file', default=[])
files = Files()
for filename in ['./file1.txt', './file2.txt']:
with open(filename, 'rb') as f:
content = f.read()
files.root.append(File(name=filename, content=content))
expected_xml_doc = pathlib.Path('./doc.xml').read_bytes()
assert canonicalize(files.to_xml(), strip_text=True) == canonicalize(expected_xml_doc, strip_text=True)
```
--------------------------------
### Nested Wrappers with Namespaces
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/wrapper.md
Demonstrates how to use nested `pydantic_xml.wrapped()` calls to extract data from sub-elements across different namespaces. Each `wrapped` call can specify its own namespace and namespace map.
```python
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'},
),
),
)
```
--------------------------------
### Inherit Namespace for Model Fields
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/elements.md
Declare namespace and mapping for a model to inherit them for all primitive fields. Sub-models do not inherit namespaces automatically and must define them explicitly.
```python
class Company(
BaseXmlModel,
tag='company',
ns='co',
nsmap={'co': 'http://www.company.com/co'},
):
founded: dt.date = element()
website: HttpUrl = element(tag='web-site', ns='co')
```
--------------------------------
### XML Document for SOAP Request
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/generics.md
This XML document represents a SOAP envelope containing a `BasicAuth` in the header and a `CreateCompanyMethod` in the body. It includes namespace declarations for SOAP, authentication, and company-specific elements.
```xml
adminsecretSpaceX2002-03-14https://www.spacex.com
```
--------------------------------
### Drop Empty Elements with skip_empty=True
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/misc.md
Inherit from `BaseXmlModel` with `skip_empty=True` to automatically drop fields with empty values (including `None`) during XML serialization. This results in a more concise XML output.
```python
from typing import Optional
from pydantic_xml import BaseXmlModel, element
class Company(BaseXmlModel, skip_empty=True):
title: Optional[str] = element(default=None)
company = Company()
assert company.to_xml() == b''
```
--------------------------------
### JSON for TypedDict Attributes
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/mappings.md
Corresponding JSON representation for the XML with TypedDict attributes, mapping to the 'info' dictionary.
```json
{
"info": {
"founded": "2002-03-14",
"employees": 12000,
"website": "https://www.spacex.com"
}
}
```
--------------------------------
### Defining Generic XML Models
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/generics.md
Define a generic `Request` model that accepts a type variable `AuthType`. This allows for different authentication structures within the same request model. Specialized request types like `BasicRequest` and `TokenRequest` are created by providing concrete types for `AuthType`.
```python
from typing import TypeVar
from uuid import UUID
from pydantic import SecretStr
from pydantic_xml import BaseXmlModel, attr, element
AuthType = TypeVar('AuthType')
class Request(BaseXmlModel, Generic[AuthType], tag='request'):
request_id: UUID = attr(name='id')
timestamp: float = attr()
auth: AuthType
class BasicAuth(BaseXmlModel):
user: str = attr()
password: SecretStr = attr()
class TokenAuth(BaseXmlModel):
token: UUID = element()
BasicRequest = Request[BasicAuth]
TokenRequest = Request[TokenAuth]
```
--------------------------------
### Exclude Unset Values with exclude_unset=True
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/misc.md
Employ `exclude_unset=True` in `to_xml()` to omit fields that have not been explicitly set, even if they have a default value. This differs from `exclude_none` by considering fields that were never assigned a value.
```python
class Product(BaseXmlModel, tag='Product'):
title: Optional[str] = element(tag='Title', default=None)
status: Optional[Literal['running', 'development']] = element(tag='Status', default=None)
launched: Optional[int] = element(tag='Launched', default=None)
product = Product(title="Starlink", status=None)
xml = product.to_xml(exclude_unset=True)
```
```xml
Starlink
```
--------------------------------
### Annotated typing for custom XML serialization
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/misc.md
Utilize the `Annotated` typing form to attach metadata, including custom validators and serializers, directly to type hints. This approach offers a cleaner way to define reusable serialization and validation logic for fields.
```python
import pathlib
from typing import Annotated, List, Type
from xml.etree.ElementTree import canonicalize
import pydantic_xml as pxml
from pydantic_xml.element import XmlElementReader, XmlElementWriter
def validate_space_separated_list(
cls: Type[pxml.BaseXmlModel],
element: XmlElementReader,
field_name: str,
) -> List[float]:
if element := element.pop_element(field_name, search_mode=cls.__xml_search_mode__):
return list(map(float, element.pop_text().split()))
return []
def serialize_space_separated_list(
model: pxml.BaseXmlModel,
element: XmlElementWriter,
value: List[float],
field_name: str,
) -> None:
sub_element = element.make_element(tag=field_name, nsmap=None)
sub_element.set_text(' '.join(map(str, value)))
element.append_element(sub_element)
SpaceSeparatedValueList = Annotated[
List[float],
pxml.XmlFieldValidator(validate_space_separated_list),
pxml.XmlFieldSerializer(serialize_space_separated_list),
]
class Plot(pxml.BaseXmlModel):
x: SpaceSeparatedValueList = pxml.element()
y: SpaceSeparatedValueList = pxml.element()
xml_doc = pathlib.Path('./doc.xml').read_text()
plot = Plot.from_xml(xml_doc)
assert canonicalize(plot.to_xml(), strip_text=True) == canonicalize(xml_doc, strip_text=True)
```
--------------------------------
### Exclude None Values with exclude_none=True
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/misc.md
Use the `exclude_none=True` parameter in `to_xml()` to exclude fields with `None` values from the generated XML. This is useful for cleaning up output when optional fields are not set.
```python
class Product(BaseXmlModel, tag='Product'):
title: Optional[str] = element(tag='Title', default=None)
status: Optional[Literal['running', 'development']] = element(tag='Status', default=None)
launched: Optional[int] = element(tag='Launched', default=None)
product = Product(title="Starlink", status=None)
xml = product.to_xml(exclude_none=True)
```
```xml
Starlink
```
--------------------------------
### Define Raw Element Typed Fields
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/raw.md
Annotate fields with `Element` and set `arbitrary_types_allowed=True` to handle raw XML elements. This is useful when the schema is unknown or complex.
```python
class Contact(BaseXmlModel, tag='contact'):
url: HttpUrl
class Contacts(
BaseXmlModel,
tag='contacts',
arbitrary_types_allowed=True,
):
contacts_raw: List[Element] = element(tag='contact', exclude=True)
@computed_element
def parse_raw_contacts(self) -> List[Contact]:
contacts: List[Contact] = []
for contact_raw in self.contacts_raw:
if url := contact_raw.attrib.get('url'):
contact = Contact(url=url)
elif (link := contact_raw.find('link')) is not None:
contact = Contact(url=link.text)
else:
contact = Contact(url=contact_raw.text.strip())
contacts.append(contact)
return contacts
```
--------------------------------
### Custom Datetime Encoding for XML
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/misc.md
Demonstrates how to use `@field_serializer` to customize the XML encoding of a datetime field to a float timestamp. This is useful for specific serialization requirements.
```python
class File(BaseXmlModel):
created: datetime = element()
@field_serializer('created')
def encode_created(self, value: datetime) -> float:
return value.timestamp()
```
--------------------------------
### JSON for Local Element Attributes
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/mappings.md
Corresponding JSON representation for the XML with local attributes, mapping to the 'properties' dictionary.
```json
{
"properties": {
"trade-name": "SpaceX",
"type": "Private"
}
}
```
--------------------------------
### XML Representation of BasicAuth Request
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/generics.md
This XML snippet shows a `request` element with a `BasicAuth` nested within its `auth` tag. It includes attributes for `id`, `timestamp`, and `user`/`password` for authentication.
```xml
```
--------------------------------
### Defaulting to Empty String for Element Text
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/text.md
To deserialize empty element text as an empty string (`""`), provide `""` as the default value for the field.
```python
class Company(BaseXmlModel):
description: str = ""
```
--------------------------------
### Custom Root Type for Model List
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/models.md
Implement a custom root type for a list of model types. This enables the model to represent a collection of structured items, where each item conforms to a specified model.
```python
class Socials(RootXmlModel, tag='socials'):
root: List[HttpUrl] = element(tag='social')
class Contacts(RootXmlModel[Socials], tag='contacts'):
pass
```
--------------------------------
### Define XML Models for Hierarchical Data
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/models.md
Define Pydantic models for XML elements, including nested structures and attributes. Use `attr` for attributes and `element` for nested elements.
```python
import pathlib
from typing import List, Optional
from pydantic_xml import BaseXmlModel, attr, element
class File(BaseXmlModel, tag="File"):
name: str = attr(name='Name')
mode: str = attr(name='Mode')
class Directory(BaseXmlModel, tag="Directory"):
name: str = attr(name='Name')
mode: str = attr(name='Mode')
dirs: Optional[List['Directory']] = element(tag='Directory', default=None)
files: Optional[List[File]] = element(tag='File', default_factory=list)
```
--------------------------------
### Define Company Model with XML Attributes, Elements, and Nested Lists
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/index.md
This Python code defines a Company model using pydantic-xml. It showcases mapping XML attributes ('trade-name'), element text ('website'), and nested elements ('product') using `attr()`, `element()`, and `List` with a specified tag. It also includes default values for optional fields.
```python
class Company(BaseXmlModel):
trade_name: str = attr(name='trade-name') # extracted from the 'trade-name' attribute
website: HttpUrl = element() # extracted from the 'element' text
products: List[Product] = element(tag='product', default=[]) # extracted from the 'Company' element's children
```
--------------------------------
### JSON Document for SOAP Request
Source: https://github.com/dapper91/pydantic-xml/blob/master/docs/source/pages/data-binding/generics.md
This JSON document represents the parsed SOAP request. It shows the nested structure of the header (containing `auth` with `user` and `password`) and the body (containing `call` with `trade_name`, `founded`, and `website`).
```json
{
"header": {
"auth": {
"user": "admin",
"password": "secret"
}
},
"body": {
"call": {
"trade_name": "SpaceX",
"founded": "2002-03-14",
"website": "https://www.spacex.com"
}
}
}
```