Parsing XML with namespace in Python via 'ElementTree'
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
XML namespaces prevent element name collisions when combining documents from different sources. Python's ElementTree requires you to include the full namespace URI in every tag lookup, which makes code verbose. The practical approach is to define a namespace dictionary and pass it to find() and findall(). Without this, your XPath queries silently return no results because ElementTree treats unqualified names and namespace-qualified names as different tags.
The Problem
ElementTree does not understand the ns: prefix from the XML file. You must use the full namespace URI.
Method 1: Full Namespace URI (Verbose)
This works but is hard to read with long URIs.
Method 2: Namespace Dictionary (Recommended)
The prefix in your dictionary (ns) does not need to match the prefix in the XML file. It is just a local alias for the URI.
Method 3: Default Namespace
Many XML documents use a default namespace (no prefix):
You must assign a prefix (d) in your dictionary for the default namespace.
Extracting Namespaces Automatically
Using iterparse to Collect All Namespaces
Multiple Namespaces
Using lxml (More Powerful Alternative)
lxml has better namespace support and full XPath:
Real-World Example: Parsing an Atom Feed
Common Pitfalls
- Omitting the namespace in
find()/findall(): Without the namespace,findall('item')returns an empty list even though the XML clearly has<item>elements. Elements in a namespace and elements without one are different tags. - Using the XML prefix instead of your dict prefix:
findall('ns:item', ns)only works if your namespace dict has the key'ns'. The prefix in the dict is what matters, not the prefix in the XML file. - Default namespace confusion:
<root xmlns="...">applies the namespace to all child elements without a prefix. You still need to specify the namespace in everyfind()call. Nonefromfind()when element is missing:find()returnsNoneif the element is not found (often due to missing namespace). Accessing.textonNoneraisesAttributeError. Always check:elem = node.find('ns:name', ns); text = elem.text if elem is not None else ''.ET.register_namespace()is for writing, not reading:ET.register_namespace('ns', 'http://...')controls how namespaces appear when serializing XML. It does not affect parsing orfind()/findall().
Summary
- Pass a namespace dict to
find()andfindall():root.findall('ns:item', {'ns': 'http://...'}) - The dict prefix is your local alias — it does not need to match the XML file's prefix
- Default namespaces (
xmlns="...") still require explicit namespace handling - Use
iterparsewith'start-ns'events to extract namespaces automatically - Use
lxmlinstead ofElementTreefor full XPath and better namespace handling - Always check for
Nonereturns fromfind()before accessing.text
Related reading
- partial string formatting
- Pass a list to a function to act as multiple arguments
- Pass keyword arguments to target function in Python threading.Thread
- pass kwargs argument to another function with kwargs
- Passing a dictionary to a function as keyword parameters
- Passing functions with arguments to another function in Python?
- Passing HTML to template using Flask/Jinja2
- passing supplementary parameters to hyperopt objective function
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.