XML Tutorial · XML in Code · Lesson 17 of 28

XML in Python

Reading, building and writing XML in Python with the standard library's ElementTree and with lxml, and when to use which.

Create a free account to save this page, take notes and track your progress. Sign in

ElementTree or lxml?

xml.etree.ElementTree (standard library) lxml
Install Built in pip install lxml
XPath A limited subset (findall("./item[@qty]")) Full XPath 1.0
XSLT, XSD, RELAX NG, Schematron No Yes
Speed Fast (C accelerator) Faster, plus streaming tools
Parent pointers (getparent()) No Yes
API ElementTree ElementTree-compatible, plus extras

Start with ElementTree for simple reading and writing; use lxml for XPath, validation, XSLT or big documents. For untrusted input, read XML security first.

Reading with ElementTree

Read with the standard libraryTry it yourself
import xml.etree.ElementTree as ET

root = ET.fromstring("""<shop>
  <product sku="TEA-01" category="drinks"><name>Green tea</name><price>3.50</price><stock>40</stock></product>
  <product sku="COF-02" category="drinks"><name>Coffee beans</name><price>9.90</price><stock>0</stock></product>
  <product sku="MUG-07" category="kitchen"><name>Camel mug</name><price>12.00</price><stock>15</stock></product>
  <product sku="PAN-03" category="kitchen"><name>Frying pan</name><price>29.00</price><stock>4</stock></product>
</shop>""")
for p in root.findall("product"):
    print(p.get("sku"), p.findtext("name"), float(p.findtext("price")))
print("in stock:", [p.findtext("name") for p in root.findall("product") if int(p.findtext("stock")) > 0])
print("kitchen:", [p.get("sku") for p in root.findall("product[@category='kitchen']")])

Output

TEA-01 Green tea 3.5
COF-02 Coffee beans 9.9
MUG-07 Camel mug 12.0
PAN-03 Frying pan 29.0
in stock: ['Green tea', 'Camel mug', 'Frying pan']
kitchen: ['MUG-07', 'PAN-03']

Building and writing XML

Build and serialiseTry it yourself
import xml.etree.ElementTree as ET

order = ET.Element("order", id="1042")
ET.SubElement(order, "customer").text = "Ada & Co"
for sku, qty in [("TEA-01", 2), ("MUG-07", 1)]:
    ET.SubElement(order, "item", sku=sku, qty=str(qty))
ET.indent(order)                        # pretty-print (Python 3.9+)
print(ET.tostring(order, encoding="unicode"))
print(ET.tostring(order, xml_declaration=True, encoding="UTF-8")[:38])

Output

<order id="1042">
  <customer>Ada &amp; Co</customer>
  <item sku="TEA-01" qty="2" />
  <item sku="MUG-07" qty="1" />
</order>
b"<?xml version='1.0' encoding='UTF-8'?>"

Modifying a document

Change and saveTry it yourself
from lxml import etree

shop = etree.fromstring(b"""<shop>
  <product sku="TEA-01" category="drinks"><name>Green tea</name><price>3.50</price><stock>40</stock></product>
  <product sku="COF-02" category="drinks"><name>Coffee beans</name><price>9.90</price><stock>0</stock></product>
  <product sku="MUG-07" category="kitchen"><name>Camel mug</name><price>12.00</price><stock>15</stock></product>
  <product sku="PAN-03" category="kitchen"><name>Frying pan</name><price>29.00</price><stock>4</stock></product>
</shop>""")
for p in shop.xpath("//product[stock = 0]"):
    p.getparent().remove(p)                         # remove sold-out products
for price in shop.iter("price"):
    price.text = f"{float(price.text) * 1.1:.2f}"   # raise prices 10%
shop.set("updated", "2026-10-22")
print(etree.tostring(shop, pretty_print=True).decode())

Output

<shop updated="2026-10-22">
  <product sku="TEA-01" category="drinks"><name>Green tea</name><price>3.85</price><stock>40</stock></product>
  <product sku="MUG-07" category="kitchen"><name>Camel mug</name><price>13.20</price><stock>15</stock></product>
  <product sku="PAN-03" category="kitchen"><name>Frying pan</name><price>31.90</price><stock>4</stock></product>
</shop>

Test yourself

Which Python library supports XSD validation and full XPath 1.0?

  1. lxml
  2. xml.etree.ElementTree
  3. json
  4. csv
Show answer

Answer: lxml

ElementTree only supports a small XPath subset and no schemas; lxml adds both.

Was this page helpful?