Back to Blog
Python

Convert XML to Dictionary and Back with Python xmltodict

python xmltodict convert xml to dictionary and back: Learn how to use Python's xmltodict to parse XML into dictionaries and serialize dictionaries back to XML, includi...

xmltodictXML parsingPython dictionariesXML serializationPython
A diagram showing XML data on the left transforming into a Python dictionary on the right, and back again, representing bidirectional conversion.

python xmltodict convert xml to dictionary and back requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

When you need to convert XML to a dictionary and back in Python, the xmltodict library is one of the most direct options. It turns XML into native Python structures and can serialize those structures back into XML. This article explains how to use xmltodict for both directions, how to handle attributes and namespaces, and what limitations you should be aware of before relying on it in production.

Why Use xmltodict for XML and Dictionary Conversion

xmltodict is designed for developers who want to treat XML like JSON. Instead of navigating the XML tree with ElementTree methods, you get a plain dictionary (or OrderedDict) that you can access with keys. This is particularly convenient when you are working with APIs that return XML but you prefer to manipulate data as dictionaries. The library also supports serialization back to XML, making it a complete round-trip solution for many common use cases.

Installing xmltodict

Install the library with pip:

pip install xmltodict

The library has no external dependencies, so it works in most Python environments, including virtual environments and containers.

Converting XML to a Dictionary

The parse function takes an XML string or file-like object and returns an OrderedDict by default. Here is a minimal example:

import xmltodict xml_string = """ <book> <title>Learning Python</title> <author>Mark Lutz</author> <price>39.99</price> </book> """ book_dict = xmltodict.parse(xml_string) print(book_dict)

The output is:

OrderedDict([('book', OrderedDict([('title', 'Learning Python'), ('author', 'Mark Lutz'), ('price', '39.99')]))])

Each element becomes a key, and the text content becomes the value. If you prefer a regular dict, you can pass dict_constructor=dict to parse, or convert the result later.

Converting a Dictionary Back to XML

To go the other direction, use unparse. The dictionary must have exactly one top-level key, which becomes the root element.

import xmltodict book_dict = { "book": { "title": "Learning Python", "author": "Mark Lutz", "price": "39.99" } } xml_output = xmltodict.unparse(book_dict, pretty=True) print(xml_output)

The pretty=True argument adds indentation for readability. Without it, the output is a single line. The unparse function accepts additional options like indent to control the indentation string.

Handling Attributes and Text Nodes

XML attributes are represented with a leading @ in the dictionary keys. For example:

xml_string = """ <book id="123"> <title>Learning Python</title> <author>Mark Lutz</author> </book> """ book_dict = xmltodict.parse(xml_string) print(book_dict)

Output:

OrderedDict([('book', OrderedDict([('@id', '123'), ('title', 'Learning Python'), ('author', 'Mark Lutz')]))])

When an element has both attributes and child elements, the text content is stored under the #text key. Consider this XML:

<message id="42">Hello, world!</message>

Parsing it yields:

OrderedDict([('message', OrderedDict([('@id', '42'), ('#text', 'Hello, world!')]))])

You can customize these prefixes using the attr_prefix and cdata_key parameters in both parse and unparse.

Dealing with Namespaces

By default, xmltodict does not process namespaces. That means keys retain the namespace prefix exactly as it appears in the XML. For example:

xml_string = """ <ns:book xmlns:ns="http://example.com/ns"> <ns:title>Learning Python</ns:title> </ns:book> """ book_dict = xmltodict.parse(xml_string) print(book_dict)

Output:

OrderedDict([('ns:book', OrderedDict([('ns:title', 'Learning Python')]))])

If you set process_namespaces=True, the keys use the full namespace URI instead of the prefix:

book_dict = xmltodict.parse(xml_string, process_namespaces=True) print(book_dict)

Output:

OrderedDict([('http://example.com/ns:book', OrderedDict([('http://example.com/ns:title', 'Learning Python')]))])

You can also change the separator between the URI and the local name with the namespace_separator parameter. When unparsing, you must provide the same namespace configuration to get a consistent result.

Round-Trip Limitations and Common Pitfalls

Converting XML to a dictionary and back is not always lossless. The library makes pragmatic choices that can alter the original XML. For example:

  • Attribute order is not preserved. The dictionary stores attributes in the order they appear, but when unparsing, they may be reordered.
  • Comments and processing instructions are dropped entirely.
  • CDATA sections become plain text, and the <![CDATA[...]]> wrapper is lost.
  • The unparse function always generates a declaration unless you disable it, and it may add or remove whitespace.

Consider this XML:

<root> <item>value</item> </root>

After a round trip, the output might be:

<root><item>value</item></root>

The whitespace and indentation are not preserved. If you need to maintain the exact byte representation, xmltodict is not the right tool.

Performance and Memory Considerations

xmltodict builds a complete dictionary in memory. For large XML files, this can consume significant memory and cause high latency. If you are processing multi-gigabyte documents, consider using a streaming parser like xml.etree.ElementTree.iterparse or lxml with iterative parsing. For configuration files, API responses, and other small-to-medium XML documents, xmltodict is perfectly adequate.

When to Choose xmltodict Over ElementTree

ElementTree is part of the standard library and gives you fine-grained control over namespaces, attributes, and streaming. It is the better choice when you need to preserve XML structure exactly or when you are working with very large documents. xmltodict shines when you want to quickly convert XML to a Python-friendly structure and back, especially in scripts and small services where the loss of some formatting details is acceptable.

Use xmltodict when:

  • You are integrating with an API that returns XML and you want to treat it like JSON.
  • You need to convert a small XML document to a dictionary for testing or data transformation.
  • You want to generate XML from a Python dict without writing verbose ElementTree code.

Choose ElementTree when:

  • You need to preserve the original XML formatting or comments.
  • You are processing XML streams that exceed available memory.
  • You need precise control over namespace handling and attribute order.

The decision ultimately depends on whether you value convenience and readability over exact fidelity and scalability.

python xmltodict convert xml to dictionary and back: Practic | RYUSLOG DEV