Complete reference for XML — syntax, XPath navigation, Python parsing, XSLT transformations, and XSD schema validation with copy-paste examples.
Part of The Direct Path to Linux Ubuntu — free for all.
Run Python examples with python3 script.py.
Production XML with namespaces and all syntax rules.
<?xml version="1.0" encoding="UTF-8"?>
<!-- MyWebUniversity — XML example document -->
<!-- Rules: close all tags, quote attributes, escape & < > -->
<catalog xmlns="https://www.mywebuniversity.com/catalog/v2"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.mywebuniversity.com/catalog/v2 catalog.xsd">
<course id="CS101" level="beginner" available="true">
<dc:title>Introduction to Python Programming</dc:title>
<dc:creator>Dr. Alice Brown</dc:creator>
<dc:date>2026-09-01</dc:date>
<description>
Learn Python from scratch: variables, loops, functions,
and object-oriented programming. & includes hands-on projects.
</description>
<!-- CDATA for content with special chars -->
<code_sample><![CDATA[
def factorial(n):
return 1 if n <= 1 else n * factorial(n-1)
print(factorial(10)) # Output: 3628800
]]></code_sample>
<prerequisites/> <!-- empty element -->
<outcomes>
<outcome>Write Python scripts</outcome>
<outcome>Use standard library</outcome>
<outcome>Understand OOP concepts</outcome>
</outcomes>
<price currency="USD" discount="0.00">0.00</price>
</course>
</catalog>Read, navigate, and modify XML with Python's built-in library.
import xml.etree.ElementTree as ET
# Parse from string
xml = '''<library>
<book id="1" available="true">
<title>Learning Go</title>
<author>Jon Bodner</author>
<year>2021</year>
<price>39.99</price>
</book>
<book id="2" available="false">
<title>The Rust Programming Language</title>
<author>Steve Klabnik</author>
<year>2019</year>
<price>29.99</price>
</book>
<book id="3" available="true">
<title>Python Cookbook</title>
<author>David Beazley</author>
<year>2013</year>
<price>49.99</price>
</book>
</library>'''
root = ET.fromstring(xml)
# Find all books
for book in root.findall('book'):
print(f"[{book.get('id')}] {book.findtext('title')} "
f"by {book.findtext('author')} (${book.findtext('price')})")
# Filter: available only
print("\nAvailable:")
for b in root.findall("book[@available='true']"):
print(f" {b.findtext('title')}")
# Aggregate
prices = [float(b.findtext('price')) for b in root.findall('book')]
print(f"\nTotal: ${sum(prices):.2f} Avg: ${sum(prices)/len(prices):.2f}")
# Add a new book
new = ET.SubElement(root, 'book', id='4', available='true')
ET.SubElement(new, 'title').text = 'Designing Data-Intensive Applications'
ET.SubElement(new, 'author').text = 'Martin Kleppmann'
ET.SubElement(new, 'year').text = '2017'
ET.SubElement(new, 'price').text = '44.99'
ET.indent(root, space=' ')
print("\nAfter adding book 4:")
print(ET.tostring(root, encoding='unicode')[:300])
# python3 xml_parse.pyConvert XML documents to JSON format.
import xml.etree.ElementTree as ET
import json
def xml_to_dict(element):
result = {}
# Attributes
if element.attrib:
result.update({f"@{k}": v for k, v in element.attrib.items()})
# Children
children = list(element)
if children:
child_dict = {}
for child in children:
child_data = xml_to_dict(child)
tag = child.tag
if tag in child_dict:
if not isinstance(child_dict[tag], list):
child_dict[tag] = [child_dict[tag]]
child_dict[tag].append(child_data)
else:
child_dict[tag] = child_data
result.update(child_dict)
# Text content
text = (element.text or '').strip()
if text:
if result:
result['#text'] = text
else:
return text
return result or None
xml_str = '''<students>
<student id="1001" status="active">
<name>Alice Smith</name>
<gpa>3.95</gpa>
<course grade="A">Python</course>
<course grade="A-">JavaScript</course>
</student>
<student id="1002" status="active">
<name>Bob Jones</name>
<gpa>3.72</gpa>
<course grade="B+">Python</course>
</student>
</students>'''
root = ET.fromstring(xml_str)
data = {root.tag: xml_to_dict(root)}
print(json.dumps(data, indent=2))
# python3 xml_to_json.pyCreate XML programmatically and write to file.
import xml.etree.ElementTree as ET
from datetime import date
def make_report(students):
root = ET.Element('report',
generated=date.today().isoformat(),
version='1.0',
source='MyWebUniversity'
)
summary = ET.SubElement(root, 'summary')
ET.SubElement(summary, 'total').text = str(len(students))
ET.SubElement(summary, 'active').text = str(sum(1 for s in students if s['active']))
avg_gpa = sum(s['gpa'] for s in students) / len(students)
ET.SubElement(summary, 'avg_gpa').text = f"{avg_gpa:.3f}"
students_el = ET.SubElement(root, 'students')
for s in sorted(students, key=lambda x: -x['gpa']):
st = ET.SubElement(students_el, 'student',
id=str(s['id']),
status='active' if s['active'] else 'inactive'
)
ET.SubElement(st, 'name').text = s['name']
ET.SubElement(st, 'email').text = s['email']
ET.SubElement(st, 'gpa').text = str(s['gpa'])
ET.SubElement(st, 'grade').text = 'A' if s['gpa'] >= 3.7 else 'B'
courses_el = ET.SubElement(st, 'courses')
for c in s.get('courses', []):
ET.SubElement(courses_el, 'course',
code=c['code'], credits=str(c['credits'])
).text = c['name']
return root
students = [
{'id':1,'name':'Alice','email':'a@u.edu','gpa':3.95,'active':True,
'courses':[{'code':'CS101','credits':3,'name':'Python'},
{'code':'CS201','credits':3,'name':'JavaScript'}]},
{'id':2,'name':'Bob', 'email':'b@u.edu','gpa':3.72,'active':True,
'courses':[{'code':'CS101','credits':3,'name':'Python'}]},
{'id':3,'name':'Carol','email':'c@u.edu','gpa':3.88,'active':False,
'courses':[]},
]
root = make_report(students)
ET.indent(root, space=' ')
tree = ET.ElementTree(root)
tree.write('report.xml', encoding='utf-8', xml_declaration=True)
print("Written report.xml:")
print(ET.tostring(root, encoding='unicode')[:500])
# python3 generate_xml.pyWorking with XML namespaces in Python.
import xml.etree.ElementTree as ET
# XML with multiple namespaces
xml = '''<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="https://mywebuniversity.com/default"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:xlink="http://www.w3.org/1999/xlink">
<course id="CS101">
<dc:title>Introduction to Python</dc:title>
<dc:creator>Dr. Brown</dc:creator>
<dc:date>2026-09-01</dc:date>
<resource xlink:href="https://mywebuniversity.com/python"
xlink:type="simple">Course Materials</resource>
</course>
</root>'''
# Register namespaces for cleaner output
ET.register_namespace('', 'https://mywebuniversity.com/default')
ET.register_namespace('dc', 'http://purl.org/dc/elements/1.1/')
ET.register_namespace('xlink','http://www.w3.org/1999/xlink')
root = ET.fromstring(xml)
# Must use Clark notation {uri}localname with ElementTree
NS = {
'': 'https://mywebuniversity.com/default',
'dc': 'http://purl.org/dc/elements/1.1/',
'xlink': 'http://www.w3.org/1999/xlink',
}
for course in root.findall('{https://mywebuniversity.com/default}course'):
cid = course.get('id')
title = course.findtext('{http://purl.org/dc/elements/1.1/}title')
res = course.find('{https://mywebuniversity.com/default}resource')
href = res.get('{http://www.w3.org/1999/xlink}href') if res is not None else ''
print(f" [{cid}] {title}")
print(f" Link: {href}")
print("\nNote: Use lxml for cleaner namespace handling with XPath")
# pip install lxml
# from lxml import etree
# tree = etree.fromstring(xml.encode())
# ns = {'dc':'http://purl.org/dc/elements/1.1/','u':'https://mywebuniversity.com/default'}
# print(tree.xpath('//dc:title/text()', namespaces=ns))
# python3 namespaces.py