dapper91 / pydantic-xml

python xml for humans
https://pydantic-xml.readthedocs.io
The Unlicense
141 stars 14 forks source link

Question about Namespaces #133

Closed gizmo84 closed 8 months ago

gizmo84 commented 9 months ago

First I want to thanks you for your amazing work ! It currently saves us a lot of pain parsing some weird XML structures :)

I have a question regarding XML Namespaces. Given the following model, I'm able to parse and generate a given XML stream.

from pydantic_xml import BaseXmlModel, element, attr

nsmap = {
    'co': 'http://company.org/co',
    'cl': 'http://company.org/cl',
}

class Company(
    BaseXmlModel,
    nsmap=nsmap,
):
    trade_name: str = attr(name='trade-name', ns='co')
    type: str = attr(ns='cl')

The corresponding XML:

<Company co:trade-name="SpaceX"
         cl:type="Private"
         xmlns:co="http://company.org/co" xmlns:cl="http://company.org/cl"/>

However some systems out of our hands are using some alternative namespace aliases. For example comp vs. co and class vs. cl. Can a pydantic_xml model deal with such differences ?

<Company comp:trade-name="SpaceX"
         class:type="Private"
         xmlns:comp="http://company.org/co" xmlns:class="http://company.org/cl"/>
dapper91 commented 8 months ago

@gizmo84 Hi

Yes, pydantic_xml will successfully parse the both documents. Namespace aliases don't matter. It only matters that the document namespaces match the model namespaces.

But during serialization it will use aliases defined in the model not document.

>>> from pydantic_xml import BaseXmlModel, attr
>>>
>>> nsmap = {
...     'co': 'http://company.org/co',
...     'cl': 'http://company.org/cl',
... }
>>>
>>> class Company(
...     BaseXmlModel,
...     nsmap=nsmap,
... ):
...     trade_name: str = attr(name='trade-name', ns='co')
...     type: str = attr(ns='cl')
...
>>>
>>> xml = '''
... <Company co:trade-name="SpaceX"
...          cl:type="Private"
...          xmlns:co="http://company.org/co" xmlns:cl="http://company.org/cl"/>
... '''
>>>
>>> c = Company.from_xml(xml)
>>> print(c)
trade_name='SpaceX' type='Private'
>>> print(c.to_xml())
b'<Company xmlns:co="http://company.org/co" xmlns:cl="http://company.org/cl" co:trade-name="SpaceX" cl:type="Private"/>'
>>>
>>>
>>> xml = '''
... <Company comp:trade-name="SpaceX"
...          class:type="Private"
...          xmlns:comp="http://company.org/co" xmlns:class="http://company.org/cl"/>
... '''
>>>
>>> c = Company.from_xml(xml)
>>> print(c)
trade_name='SpaceX' type='Private'
>>> print(c.to_xml())
b'<Company xmlns:co="http://company.org/co" xmlns:cl="http://company.org/cl" co:trade-name="SpaceX" cl:type="Private"/>'
>>>