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.
Using xml.etree.ElementTree (Recommended)
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 dicttoxmlimport 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 & Cream</item>
<item>Ben's Choice</item>
<item>Size: 5" x 3"</item>
<item>Price < $10</item>
</items>Special characters are automatically escaped (& becomes &, < becomes <), 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.ElementTreeis the recommended built-in solution for most projects. It is efficient, handles special characters automatically, and provides clean pretty printing withET.indent()in Python 3.9+.xml.dom.minidomprovides a DOM-based interface with built-in pretty printing across all Python 3 versions, though its API is more verbose.dicttoxmloffers 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.