Namespaces
How URIs disambiguate element names, how default and prefixed namespaces differ, and the attribute trap that breaks XPath queries.
Why namespaces exist
Two vocabularies can both define an element called <title>. A namespace makes the name globally unambiguous by binding a prefix to a URI. The URI is an identifier, not an address — nothing is ever fetched from it.
| Term | Example | Meaning |
|---|---|---|
| Prefix | svg | A local alias, arbitrary and rebindable |
| Namespace URI | http://www.w3.org/2000/svg | The globally unique identity |
| Local name | rect | The part after the colon |
| Qualified name | svg:rect | Prefix plus local name |
| Default namespace | xmlns="..." | Applies to unprefixed elements only |
Declaring and using them
<!-- prefix declarations are scoped to the element and its descendants -->
<root xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:x="http://www.w3.org/1999/xhtml">
<dc:title>Namespaces</dc:title>
<x:p>Body text</x:p>
</root>
<!-- a default namespace: every unprefixed element belongs to it -->
<feed xmlns="http://www.w3.org/2005/Atom">
<entry>
<id>urn:uuid:1</id> <!-- same namespace as feed -->
</entry>
</feed>
<!-- undeclaring it puts an element back in no namespace -->
<feed xmlns="http://www.w3.org/2005/Atom">
<entry xmlns="">
<id>no-namespace-here</id>
</entry>
</feed>- Prefixes are local aliases: the same URI may appear as
dcin one document anddctermsin another. - Because the URI defines identity, renaming a prefix never changes a document's meaning.
xml:langandxml:spacelive in the reserved namespacehttp://www.w3.org/XML/1998/namespaceand need no declaration.- Two elements with the same local name in different namespaces are unrelated to any parser.
⚠️
A default namespace does not apply to attributes. In
<feed xmlns="http://www.w3.org/2005/Atom" type="x"> the element is in the Atom namespace while type is in no namespace — which is exactly where an XPath predicate looking for @type will fail.Working with namespaced documents
Namespaces are the most common reason an XPath query silently returns nothing. In XPath 1.0 an unprefixed name selects from the no-namespace set and never from the document's default namespace.
from lxml import etree
doc = etree.fromstring(b'<feed xmlns="http://www.w3.org/2005/Atom"><id>u1</id></feed>')
print(doc.xpath("/feed")) # [] - no namespace match
ns = {"a": "http://www.w3.org/2005/Atom"}
print(doc.xpath("/a:feed/a:id/text()", namespaces=ns)) # ['u1']
# a local-name() test avoids registering a prefix, but cannot use indexes
print(doc.xpath("/*[local-name()='feed']/*[local-name()='id']/text()"))- Register a prefix for every namespace present before writing queries.
- URIs must match character for character — a trailing slash selects nothing.
- In XPath 2.0 and later you can set a default element namespace, which is why modern XSLT avoids some of this.
- When merging documents, rewrite URIs only when the meaning changed; never rewrite prefixes to make them look tidy.
FAQ
Is the namespace URI ever fetched?
No. It exists purely for identity, which is why it can be a URL that returns 404 or an opaque URN. Parsers never resolve it.
Can two prefixes bind to the same URI?
Yes, and both are legal. They select the same elements, so pick one convention per document for readability.
Related
XML syntax and well-formedness Location paths and axes
Last refreshed 2026-09-18.