How to Convert Lists to XML in Python
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"]
# Create the root element
root = ET.Element("fruits")
# Add each list item as a child element
for fruit in fruits:
item = ET.SubElement(root, "fruit")
item.text = fruit
# Pretty print (Python 3.9+) and display
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>
- Use attributes for simple metadata like IDs, names, or single values that will not contain special characters or span multiple lines.
- Use child elements for complex data, multi-line text, or values that might contain characters reserved in XML.
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"]
# Create the document and root element
doc = Document()
root = doc.createElement("colors")
doc.appendChild(root)
# Add each list item
for color in colors:
element = doc.createElement("color")
text_node = doc.createTextNode(color)
element.appendChild(text_node)
root.appendChild(element)
# Generate pretty-printed XML
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
# Simple 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
# 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
# Nested lists (e.g., a matrix)
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"]
# Convert list to XML bytes
xml_bytes = dicttoxml.dicttoxml(data, custom_root="fruits", item_func=lambda x: "fruit")
# Pretty print the result
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>
dicttoxml automatically adds type attributes to elements, which can be helpful for deserialization but may not be desired in all cases. You have less control over the output format compared to ElementTree.
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.