Skip to content

How to Convert Lists to XML in Python

Learn how to convert Python lists (including dictionaries and nested structures) to XML using built-in modules like xml.etree.ElementTree and xml.dom.minidom, plus third-party libraries like dicttoxml with practical code examples.

XML (Extensible Markup Language) is a widely used format for storing and exchanging structured data between systems. Converting Python lists to XML is a common task when building APIs, generating configuration files, creating data exports, or interfacing with systems that consume XML data.

In this guide, you will learn multiple methods to convert Python lists to XML, from the built-in ElementTree module to the minidom parser and third-party libraries, with practical examples for different data structures.

Python's built-in ElementTree module provides a simple and efficient API for creating, reading, and writing XML documents. It represents the XML document as a tree of elements and is the recommended approach for most use cases.

Basic List to XML Conversion

import xml.etree.ElementTree as ET

fruits = ["Apple", "Banana", "Cherry", "Date", "Elderberry"]

root = ET.Element("fruits")

for fruit in fruits:
    item = ET.SubElement(root, "fruit")
    item.text = fruit

tree = ET.ElementTree(root)
ET.indent(tree, space="  ")

print(ET.tostring(root, encoding="unicode"))

Output:

<fruits>
  <fruit>Apple</fruit>
  <fruit>Banana</fruit>
  <fruit>Cherry</fruit>
  <fruit>Date</fruit>
  <fruit>Elderberry</fruit>
</fruits>

To write the XML to a file:

tree.write("fruits.xml", encoding="utf-8", xml_declaration=True)

Converting a List of Dictionaries to XML

A more practical scenario involves converting structured data, such as a list of dictionaries, into XML with nested elements:

import xml.etree.ElementTree as ET

employees = [
    {"name": "Alice", "department": "Engineering", "salary": "90000"},
    {"name": "Bob", "department": "Marketing", "salary": "75000"},
    {"name": "Charlie", "department": "Sales", "salary": "68000"}
]

root = ET.Element("employees")

for emp in employees:
    employee = ET.SubElement(root, "employee")
    for key, value in emp.items():
        child = ET.SubElement(employee, key)
        child.text = value

tree = ET.ElementTree(root)
ET.indent(tree, space="  ")

print(ET.tostring(root, encoding="unicode"))

Output:

<employees>
  <employee>
    <name>Alice</name>
    <department>Engineering</department>
    <salary>90000</salary>
  </employee>
  <employee>
    <name>Bob</name>
    <department>Marketing</department>
    <salary>75000</salary>
  </employee>
  <employee>
    <name>Charlie</name>
    <department>Sales</department>
    <salary>68000</salary>
  </employee>
</employees>

Using Attributes Instead of Child Elements

Sometimes data is better represented as XML attributes rather than child elements, especially for simple metadata:

import xml.etree.ElementTree as ET

products = [
    {"id": "1", "name": "Laptop", "price": "999"},
    {"id": "2", "name": "Phone", "price": "699"},
    {"id": "3", "name": "Tablet", "price": "329"}
]

root = ET.Element("catalog")

for product in products:
    item = ET.SubElement(root, "product")
    for key, value in product.items():
        item.set(key, value)  # Set as attribute instead of child element

tree = ET.ElementTree(root)
ET.indent(tree, space="  ")
print(ET.tostring(root, encoding="unicode"))

Output:

<catalog>
  <product id="1" name="Laptop" price="999" />
  <product id="2" name="Phone" price="699" />
  <product id="3" name="Tablet" price="329" />
</catalog>

Using xml.dom.minidom

The minidom module provides a DOM (Document Object Model) interface for creating XML. It is more verbose than ElementTree but offers built-in pretty printing without requiring Python 3.9+:

from xml.dom.minidom import Document

colors = ["Red", "Green", "Blue", "Yellow", "Purple"]

doc = Document()
root = doc.createElement("colors")
doc.appendChild(root)

for color in colors:
    element = doc.createElement("color")
    text_node = doc.createTextNode(color)
    element.appendChild(text_node)
    root.appendChild(element)

xml_string = doc.toprettyxml(indent="  ")
print(xml_string)

Output:

<?xml version="1.0" ?>
<colors>
  <color>Red</color>
  <color>Green</color>
  <color>Blue</color>
  <color>Yellow</color>
  <color>Purple</color>
</colors>

The toprettyxml() method automatically adds the XML declaration and formats the output with the specified indentation.

Building a Reusable Conversion Function

For production use, a flexible function that handles different list structures keeps your code DRY:

import xml.etree.ElementTree as ET

def list_to_xml(data, root_name="root", item_name="item"):
    """
    Convert a list to a formatted XML string.

    Args:
        data: A list of values, dicts, or nested lists.
        root_name: Name of the root XML element.
        item_name: Name for each list item element.

    Returns:
        A formatted XML string with declaration.
    """
    root = ET.Element(root_name)

    for item in data:
        element = ET.SubElement(root, item_name)

        if isinstance(item, dict):
            for key, value in item.items():
                child = ET.SubElement(element, str(key))
                child.text = str(value)
        elif isinstance(item, (list, tuple)):
            for sub_item in item:
                sub = ET.SubElement(element, "value")
                sub.text = str(sub_item)
        else:
            element.text = str(item)

    tree = ET.ElementTree(root)
    ET.indent(tree, space="  ")
    return ET.tostring(root, encoding="unicode", xml_declaration=True)

Usage Examples

Example 1: list of values

print(list_to_xml(["Apple", "Banana", "Cherry"], "fruits", "fruit"))

Output:

<?xml version='1.0' encoding='utf-8'?>
<fruits>
  <fruit>Apple</fruit>
  <fruit>Banana</fruit>
  <fruit>Cherry</fruit>
</fruits>

Example 2: list of dictionaries

users = [
    {"name": "Alice", "role": "Admin"},
    {"name": "Bob", "role": "User"}
]
print(list_to_xml(users, "users", "user"))

Output:

<?xml version='1.0' encoding='utf-8'?>
<users>
  <user>
    <name>Alice</name>
    <role>Admin</role>
  </user>
  <user>
    <name>Bob</name>
    <role>User</role>
  </user>
</users>

Example 3: netsted lists

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(list_to_xml(matrix, "matrix", "row"))

Output:

<?xml version='1.0' encoding='utf-8'?>
<matrix>
  <row>
    <value>1</value>
    <value>2</value>
    <value>3</value>
  </row>
  <row>
    <value>4</value>
    <value>5</value>
    <value>6</value>
  </row>
  <row>
    <value>7</value>
    <value>8</value>
    <value>9</value>
  </row>
</matrix>

Using the dicttoxml Library

For quick, zero-configuration conversion, the third-party dicttoxml library handles lists and dictionaries automatically:

pip install dicttoxml
import dicttoxml
from xml.dom.minidom import parseString

data = ["Apple", "Banana", "Cherry", "Date"]

xml_bytes = dicttoxml.dicttoxml(data, custom_root="fruits", item_func=lambda x: "fruit")

xml_pretty = parseString(xml_bytes).toprettyxml(indent="  ")
print(xml_pretty)

Output:

<?xml version="1.0" ?>
<fruits>
  <fruit type="str">Apple</fruit>
  <fruit type="str">Banana</fruit>
  <fruit type="str">Cherry</fruit>
  <fruit type="str">Date</fruit>
</fruits>

Handling Special Characters

XML has reserved characters (<, >, &, ", ') that must be escaped in text content. The ElementTree module handles this escaping automatically:

import xml.etree.ElementTree as ET

items = ["Cookies & Cream", "Ben's Choice", 'Size: 5" x 3"', "Price < $10"]

root = ET.Element("items")
for item in items:
    elem = ET.SubElement(root, "item")
    elem.text = item

tree = ET.ElementTree(root)
ET.indent(tree, space="  ")
print(ET.tostring(root, encoding="unicode"))

Output:

<items>
  <item>Cookies &amp; Cream</item>
  <item>Ben's Choice</item>
  <item>Size: 5" x 3"</item>
  <item>Price &lt; $10</item>
</items>

Special characters are automatically escaped (& becomes &amp;, < becomes &lt;), ensuring the output is always valid XML. You never need to escape these characters manually when using ElementTree.

Quick Comparison of Methods

Method Built-in Pretty Print Ease of Use Best For
xml.etree.ElementTree Yes Yes (Python 3.9+) Easy General use, production code
xml.dom.minidom Yes Yes (all versions) Verbose When DOM API or pre-3.9 pretty print is needed
dicttoxml No (pip install) Via minidom Very easy Quick, automatic conversion

Conclusion

Converting Python lists to XML can be accomplished with several approaches depending on your requirements:

  • xml.etree.ElementTree is the recommended built-in solution for most projects. It is efficient, handles special characters automatically, and provides clean pretty printing with ET.indent() in Python 3.9+.
  • xml.dom.minidom provides a DOM-based interface with built-in pretty printing across all Python 3 versions, though its API is more verbose.
  • dicttoxml offers zero-configuration automatic conversion for quick tasks when you do not need fine-grained control over the output format.

For most projects, ElementTree provides the best balance of simplicity, control, and performance. Building a reusable conversion function like the list_to_xml() example above ensures consistent XML generation across your codebase regardless of the input data structure.

Navigation