XML Tutorial · XML Basics · Lesson 6 of 28

XML Namespaces

Why namespaces exist, prefixes and default namespaces, and how to query namespaced XML without getting empty results.

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

The problem namespaces solve

Two vocabularies can use the same tag name for different things: an HTML <table> and a furniture <table>. A namespace gives each name a globally unique identity: a URI plus the local name.

<catalog xmlns="urn:example:shop"
         xmlns:dc="http://purl.org/dc/elements/1.1/">
  <product sku="TEA-01">
    <dc:title>Green tea</dc:title>
    <price>3.50</price>
  </product>
</catalog>
  • xmlns="urn:example:shop" sets the default namespace for this element and its descendants without a prefix.
  • xmlns:dc="…" binds the prefix dc to a namespace URI; dc:title is in that namespace.
  • The URI is just an identifier; nothing is downloaded from it.
  • Attributes without a prefix are in no namespace, even inside a default namespace.
  • The prefix is only a shorthand. What matters is the URI: <a:x xmlns:a="urn:u"/> and <b:x xmlns:b="urn:u"/> are the same element.

APIs write a namespaced name in "Clark notation", {urn:example:shop}price.

The classic bug: empty results

Code that ignores the default namespace finds nothing:

Why your query returns nothingTry it yourself
from lxml import etree

doc = etree.fromstring(b'<catalog xmlns="urn:example:shop"><product><price>3.50</price></product></catalog>')
print("tag is really:", doc.tag)
print("without namespace:", doc.findall("product"), doc.xpath("//price"))
print("with namespace:   ", [p.text for p in doc.iter("{urn:example:shop}price")])

Output

tag is really: {urn:example:shop}catalog
without namespace: [] []
with namespace:    ['3.50']

Querying with namespaces

Map prefixes of your choice to the URIs and use them in your queries. The prefixes in the query don't need to match the document's:

Namespace-aware queriesTry it yourself
from lxml import etree

doc = etree.fromstring(b"""<catalog xmlns="urn:example:shop" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <product sku="TEA-01"><dc:title>Green tea</dc:title><price>3.50</price></product>
  <product sku="MUG-07"><dc:title>Camel mug</dc:title><price>12.00</price></product>
</catalog>""")

ns = {"s": "urn:example:shop", "dc": "http://purl.org/dc/elements/1.1/"}
for p in doc.xpath("//s:product", namespaces=ns):
    print(p.get("sku"), p.xpath("string(dc:title)", namespaces=ns), p.xpath("string(s:price)", namespaces=ns))

Output

TEA-01 Green tea 3.50
MUG-07 Camel mug 12.00

XPath 1.0 has no syntax for "the default namespace", so you always need a prefix for namespaced elements, even if the document itself uses none. In Java, remember setNamespaceAware(true); it's off by default.

Test yourself

In <shop xmlns='urn:s'><item code='1'/></shop>, which namespace is the attribute code in?

  1. urn:s
  2. No namespace
  3. The xml namespace
  4. It inherits the parent's prefix
Show answer

Answer: No namespace

Default namespaces apply to unprefixed element names only; unprefixed attributes are in no namespace.

Was this page helpful?