Convert Python dicts to XML and back using lxml
Project description
convert-dict-xml
Convert Python dicts to XML and back using lxml. Supports attributes and CDATA.
Features
- Dict to XML — supports nested dicts, attributes, CDATA sections, and lists of sibling elements
- XML to Dict — parse XML back into plain dicts or
OrderedDict - Type serialization —
bool,None,datetimehandled automatically - Round-trip — convert dict → XML → dict
Installation
pip install convert-dict-xml
Note: Requires lxml, which needs
libxml2andlibxsltsystem libraries on some platforms.
Quick Start
Dict to XML
from convert_dict_xml import Dict2XML
data = {
'@attributes': {'type': 'fiction'},
'book': ['1984', 'Foundation']
}
xml = Dict2XML('books', data).to_xml_string(xml_declaration=False)
print(xml.decode())
<books type="fiction">
<book>1984</book>
<book>Foundation</book>
</books>
XML to Dict
from convert_dict_xml import XML2Dict
result = XML2Dict(xml).to_dict()
# {'@attributes': {'type': 'fiction'}, 'book': ['1984', 'Foundation']}
For namespaced XML, use strip_namespaces=True to get clean dict keys:
xml = b'<feed xmlns="http://www.w3.org/2005/Atom"><title>Blog</title></feed>'
result = XML2Dict(xml, strip_namespaces=True).to_dict()
# {'title': 'Blog'}
Dict Conventions
Use special keys to control XML output:
| Key | Purpose | Example |
|---|---|---|
@attributes |
Set XML attributes | {'@attributes': {'id': '1'}} → <node id="1"/> |
@text |
Set text content | {'@text': 'hello'} → <node>hello</node> |
@cdata |
Wrap text in CDATA | {'@cdata': 'hello'} → <node><![CDATA[hello]]></node> |
| (list value) | Sibling elements | {'item': ['a', 'b']} → <item>a</item><item>b</item> |
Use force_cdata=True to wrap all text nodes in CDATA sections.
Text Nodes
Text can be set directly or via @text:
books = {'book': 1984}
# or
books = {'book': {'@text': 1984}}
xml = Dict2XML('books', books).to_xml_string(xml_declaration=False)
print(xml.decode())
<books>
<book>1984</book>
</books>
Attributes
books = {
'@attributes': {'type': 'fiction'},
'book': 1984
}
xml = Dict2XML('books', books).to_xml_string(xml_declaration=False)
print(xml.decode())
<books type="fiction">
<book>1984</book>
</books>
Multiple Children
Lists produce sibling elements with the same tag:
books = {
'@attributes': {'type': 'fiction'},
'book': ['1984', 'Foundation', 'Stranger in a Strange Land']
}
xml = Dict2XML('books', books).to_xml_string(xml_declaration=False)
print(xml.decode())
<books type="fiction">
<book>1984</book>
<book>Foundation</book>
<book>Stranger in a Strange Land</book>
</books>
CDATA
books = {
'book': [
{'title': '1984', 'isbn': 973534},
{'title': {'@cdata': 'Foundation'}, 'price': '$15.61', 'isbn': 573234},
]
}
xml = Dict2XML('books', books).to_xml_string(xml_declaration=False)
print(xml.decode())
<books>
<book>
<isbn>973534</isbn>
<title>1984</title>
</book>
<book>
<price>$15.61</price>
<isbn>573234</isbn>
<title><![CDATA[Foundation]]></title>
</book>
</books>
Complex Example
from collections import OrderedDict
from convert_dict_xml import Dict2XML
books = OrderedDict({
'@attributes': {'type': 'fiction'},
'book': [
{
'@attributes': {'author': 'George Orwell', 'available': None},
'title': '1984',
'isbn': 972132,
},
{
'@attributes': {'author': 'Isaac Asimov', 'available': False},
'title': {'@cdata': 'Foundation'},
'price': '$15.61',
'isbn': 5735232,
},
{
'@attributes': {'author': 'Robert A Heinlein', 'available': True},
'title': {'@cdata': 'Stranger in a Strange Land'},
'price': {'@attributes': {'discount': '10%'}, '@text': '$18.00'},
'isbn': 3412332,
},
],
})
xml = Dict2XML('books', books).to_xml_string(xml_declaration=False)
print(xml.decode()
<books type="fiction">
<book available="" author="George Orwell">
<isbn>972132</isbn>
<title>1984</title>
</book>
<book available="false" author="Isaac Asimov">
<price>$15.61</price>
<isbn>5735232</isbn>
<title><![CDATA[Foundation]]></title>
</book>
<book available="true" author="Robert A Heinlein">
<price discount="10%">$18.00</price>
<isbn>3412332</isbn>
<title><![CDATA[Stranger in a Strange Land]]></title>
</book>
</books>
API Reference
Dict2XML(root_node_name, dictionary, force_cdata=False)
| Parameter | Description |
|---|---|
root_node_name |
Name of the root XML element |
dictionary |
The dict to convert |
force_cdata |
Wrap all text nodes in CDATA sections (default False) |
| Method | Returns |
|---|---|
to_xml_string(encoding='UTF-8', pretty_print=True, xml_declaration=True) |
XML as bytes |
get_etree_object() |
The underlying lxml.etree.Element |
XML2Dict(xml, ns_clean=True, strip_namespaces=False)
| Parameter | Description |
|---|---|
xml |
XML string or bytes to parse |
ns_clean |
Clean up redundant namespace declarations (default True) |
strip_namespaces |
Remove namespace URIs from tag names in the output dict (default False) |
| Method | Returns |
|---|---|
to_dict(ordered_dict=False) |
dict (or OrderedDict if ordered_dict=True) |
get_etree_object() |
The underlying lxml.etree.Element |
Contributing
git clone https://github.com/lalitpatel/convert-dict-xml.git
cd convert-dict-xml
pip install -e ".[dev]"
pytest
License
MIT — Copyright (c) 2018 Lalit Patel
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file convert_dict_xml-1.0.0.tar.gz.
File metadata
- Download URL: convert_dict_xml-1.0.0.tar.gz
- Upload date:
- Size: 10.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a37bb22ac2743b25ee9c366c499d0e44d0ba5178573b77002eabf2bbbff8451e
|
|
| MD5 |
6fa03dfe2ef4e55b2a1387a35eba5f2c
|
|
| BLAKE2b-256 |
c113aee8c9470375b9b05861fe0dee302f5adbbe377a6e3b640d05ad9345677e
|
Provenance
The following attestation bundles were made for convert_dict_xml-1.0.0.tar.gz:
Publisher:
publish.yml on lalitpatel/convert-dict-xml
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
convert_dict_xml-1.0.0.tar.gz -
Subject digest:
a37bb22ac2743b25ee9c366c499d0e44d0ba5178573b77002eabf2bbbff8451e - Sigstore transparency entry: 1017455989
- Sigstore integration time:
-
Permalink:
lalitpatel/convert-dict-xml@ecebef59d85f42cd45999b89ac034ee12954b799 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/lalitpatel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ecebef59d85f42cd45999b89ac034ee12954b799 -
Trigger Event:
push
-
Statement type:
File details
Details for the file convert_dict_xml-1.0.0-py3-none-any.whl.
File metadata
- Download URL: convert_dict_xml-1.0.0-py3-none-any.whl
- Upload date:
- Size: 6.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5f79cfb0c281a4659fe85a190326a7288fce4ca5088c86052c01177d6ebac2ed
|
|
| MD5 |
1a8c8b2140fbd1bf520b1218b8a997b5
|
|
| BLAKE2b-256 |
d88a1a90ea343f0c49d02319c1668d5a4888098efca894d664560b57baf7560a
|
Provenance
The following attestation bundles were made for convert_dict_xml-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on lalitpatel/convert-dict-xml
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
convert_dict_xml-1.0.0-py3-none-any.whl -
Subject digest:
5f79cfb0c281a4659fe85a190326a7288fce4ca5088c86052c01177d6ebac2ed - Sigstore transparency entry: 1017456038
- Sigstore integration time:
-
Permalink:
lalitpatel/convert-dict-xml@ecebef59d85f42cd45999b89ac034ee12954b799 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/lalitpatel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ecebef59d85f42cd45999b89ac034ee12954b799 -
Trigger Event:
push
-
Statement type: