Skip to content

Commit c73c38f

Browse files
authored
Merge pull request #256 from dapper91/doc/misc
- document type declaration example added. - sub-model namespace inheritance documented.
2 parents 04d915f + 7d646af commit c73c38f

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed

docs/source/pages/data-binding/elements.rst

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,39 @@ The namespace and namespace mapping can be declared for a model. In that case al
153153
:start-after: json-start
154154
:end-before: json-end
155155

156+
.. note::
157+
**Pay attention** to the namespace inheritance rule: namespace and namespace mapping
158+
are only inherited by primitive types not sub-models. If your sub-model share
159+
the namespace with the parent model you must define it explicitly:
160+
161+
.. code-block:: python
162+
163+
from pydantic_xml import BaseXmlModel, element
164+
165+
NSMAP = {
166+
'co': 'http://www.company.com/co',
167+
}
168+
169+
class SubModel(BaseXmlModel, ns='co', nsmap=NSMAP): # define ns and nsmap explicitly
170+
field2: str = element(tag='element1')
171+
172+
class Model(BaseXmlModel, ns='co', nsmap=NSMAP):
173+
field1: str = element(tag='element1') # ns "co" is inherited by the element
174+
sub: SubModel # ns and nsmap are not inherited by the SubModel
175+
176+
model = Model(field1="value1", sub=SubModel(field2="value2"))
177+
print(model.to_xml(pretty_print=True).decode())
178+
179+
180+
.. code-block:: xml
181+
182+
<co:Model xmlns:co="http://www.company.com/co">
183+
<co:element1>value1</co:element1>
184+
<co:sub>
185+
<co:element1>value2</co:element1>
186+
</co:sub>
187+
</co:Model>
188+
156189
157190
The namespace and namespace mapping can be also applied to model types passing ``ns`` and ``nsmap``
158191
to :py:func:`pydantic_xml.element`. If they are omitted the model namespace and namespace mapping is used:

docs/source/pages/misc.rst

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,68 @@ Field specification syntax is similar to ``pydantic`` one. For more information
277277
see the `documentation <https://docs.pydantic.dev/latest/concepts/models/#dynamic-model-creation>`_.
278278

279279

280+
Document type declaration
281+
~~~~~~~~~~~~~~~~~~~~~~~~~
282+
283+
A document type declaration is an instruction that associates a particular XML document
284+
with a document type definition (DTD).
285+
286+
DTD is supported by ``lxml`` backend only so the library doesn't provide an api for that natively,
287+
but it can be easily implemented by your hand:
288+
289+
.. code-block:: python
290+
291+
from typing import Any, ClassVar, Union
292+
293+
import pydantic_xml as pxml
294+
import lxml.etree
295+
296+
297+
class DTDXmlModel(pxml.BaseXmlModel):
298+
DOC_PUBLIC_ID: ClassVar[str]
299+
DOC_SYSTEM_URL: ClassVar[str]
300+
301+
def to_xml(
302+
self,
303+
*,
304+
skip_empty: bool = False,
305+
exclude_none: bool = False,
306+
exclude_unset: bool = False,
307+
**kwargs: Any,
308+
) -> Union[str, bytes]:
309+
root = self.to_xml_tree(skip_empty=skip_empty, exclude_none=exclude_none, exclude_unset=exclude_unset)
310+
tree = lxml.etree.ElementTree(root)
311+
tree.docinfo.public_id = self.DOC_PUBLIC_ID
312+
tree.docinfo.system_url = self.DOC_SYSTEM_URL
313+
314+
return lxml.etree.tostring(tree, **kwargs)
315+
316+
317+
class Html(DTDXmlModel, tag='html'):
318+
DOC_PUBLIC_ID: ClassVar[str] = '-//W3C//DTD HTML 4.01//EN'
319+
DOC_SYSTEM_URL: ClassVar[str] = 'http://www.w3.org/TR/html4/strict.dtd'
320+
321+
title: str = pxml.wrapped('head', pxml.element())
322+
body: str = pxml.element()
323+
324+
325+
html_doc = Html(title="This is a title", body="Hello world!")
326+
xml = html_doc.to_xml(pretty_print=True)
327+
328+
print(xml.decode())
329+
330+
331+
.. code-block:: xml
332+
333+
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
334+
<html>
335+
<head>
336+
<title>This is a title</title>
337+
</head>
338+
<body>Hello world!</body>
339+
</html>
340+
341+
280342
Mypy
281343
~~~~
282344

0 commit comments

Comments
 (0)