XML Namespaces and URIs — Complete Guide to Qualified Names
In this tutorial, you'll learn about XML Namespaces and URIs. We cover key concepts, practical examples, and best practices.
XML namespaces use URIs to uniquely identify element and attribute vocabularies, preventing name collisions when combining XML from different sources — using prefixes or default namespace declarations to qualify every name.
What You'll Learn
- How namespace URIs disambiguate element names
- Declaring default vs prefixed namespaces with xmlns
- Namespace scope and inheritance rules
- Handling namespaces in XPath and parsing
Why XML Namespaces Matter
When you combine an invoice XML from accounting and a product catalog from inventory, both might use
Learning Path
flowchart LR A[XML Basics] --> B[XML DTD Validation] B --> C[XML Namespaces URIs
You are here] C --> D[XML Schema XSD] D --> E[SOAP & WSDL]
Namespace Declaration Syntax
A namespace is declared using the xmlns attribute:
<!-- Prefixed namespace -->
<bk:library xmlns:bk="http://books.example.com/ns">
<bk:book>
<bk:title>The Hobbit</bk:title>
</bk:book>
</bk:library>
<!-- Default namespace (no prefix) -->
<library xmlns="http://books.example.com/ns">
<book>
<title>The Hobbit</title>
</book>
</library>
<!-- Multiple namespaces -->
<library xmlns:bk="http://books.example.com/ns"
xmlns:inv="http://inventory.example.com/ns">
<bk:book>
<bk:title>The Hobbit</bk:title>
<inv:stock units="12"/>
</bk:book>
</library>
Default vs Prefixed Namespaces
| Aspect | Default Namespace | Prefixed Namespace |
|---|---|---|
| Declaration | xmlns="URI" |
xmlns:prefix="URI" |
| Element usage | Unqualified name | prefix:element |
| Scope | All unqualified descendants | Only elements with the prefix |
| Attributes | Not affected (no default) | Must be explicitly prefixed |
<!-- Demonstrating both -->
<catalog xmlns="http://books.example.com/ns"
xmlns:meta="http://metadata.example.com/ns">
<!-- book is in the default namespace -->
<book>
<title>The Hobbit</title>
<!-- meta:date uses the prefixed namespace -->
<meta:date added="2026-06-23"/>
</book>
</catalog>
Attributes without prefixes are always in no namespace — even inside a default namespace scope.
Namespace Scope and Inheritance
Namespaces apply to the declaring element and all descendants unless overridden:
<root xmlns:bk="http://books.example.com/ns">
<!-- bk: prefix works here -->
<bk:book>
<bk:title>The Hobbit</bk:title>
<!-- Override: inside here, local is the default -->
<local:notes xmlns:local="http://local.example.com/ns">
<local:note>A classic fantasy novel.</local:note>
</local:notes>
</bk:book>
<!-- bk: prefix still works here -->
<bk:book>
<bk:title>1984</bk:title>
</bk:book>
</root>
Scope Rules
- A namespace declaration applies to the element where it appears
- It is inherited by all descendant elements
- A descendant can override with its own
xmlnsdeclaration - The same prefix can be redeclared to a different URI (confusing — avoid)
URI vs URL — What the Namespace URI Actually Does
A namespace URI does not need to point to a real resource. It is just a unique identifier:
<!-- These are all valid namespace URIs -->
xmlns:book="http://books.example.com/ns/2026"
xmlns:book="urn:isbn:978-0547928227"
xmlns:book="http://example.com/books#schema"
The URI disambiguates names. Two elements with the same local name but different namespace URIs are completely different:
| Element | Namespace URI | Identity |
|---|---|---|
{http://books.example.com}price |
books | Book price |
{http://furniture.example.com}price |
furniture | Furniture price |
{http://inventory.example.com}price |
inventory | Wholesale cost |
They are unrelated — even though they share the local name price.
Working with Namespaces in XML Parsing
Python (lxml)
from lxml import etree
xml_data = """<?xml version="1.0" encoding="UTF-8"?>
<library xmlns:bk="http://books.example.com/ns"
xmlns:inv="http://inventory.example.com/ns">
<bk:book>
<bk:title>The Hobbit</bk:title>
<bk:author>J.R.R. Tolkien</bk:author>
<inv:stock>12</inv:stock>
</bk:book>
</library>"""
root = etree.fromstring(xml_data)
# Define namespace map
ns = {'bk': 'http://books.example.com/ns',
'inv': 'http://inventory.example.com/ns'}
# Query with namespaced XPath
titles = root.xpath('//bk:title/text()', namespaces=ns)
print('Titles:', titles)
stocks = root.xpath('//inv:stock/text()', namespaces=ns)
print('Stock counts:', stocks)
# Expected output:
# Titles: ['The Hobbit']
# Stock counts: ['12']
JavaScript (Browser)
const xmlString = `<?xml version="1.0" encoding="UTF-8"?>
<library xmlns:bk="http://books.example.com/ns"
xmlns:inv="http://inventory.example.com/ns">
<bk:book>
<bk:title>The Hobbit</bk:title>
<inv:stock units="12"/>
</bk:book>
</library>`;
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
// Define namespace resolver
function nsResolver(prefix) {
const nsMap = {
"bk": "http://books.example.com/ns",
"inv": "http://inventory.example.com/ns"
};
return nsMap[prefix] || null;
}
// Query using XPath with namespace resolver
const titles = xmlDoc.evaluate(
"//bk:title/text()", xmlDoc, nsResolver,
XPathResult.ANY_TYPE, null
);
const result = [];
let node;
while ((node = titles.iterateNext()) !== null) {
result.push(node.textContent);
}
console.log("Titles:", result);
// Expected output:
// Titles: ['The Hobbit']
Real-World Namespace Examples
SOAP Envelope
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<soap:Body>
<m:GetPrice xmlns:m="http://books.example.com/prices">
<m:Item>978-0547928227</m:Item>
</m:GetPrice>
</soap:Body>
</soap:Envelope>
XSLT Stylesheet
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:bk="http://books.example.com/ns"
xmlns="http://www.w3.org/1999/xhtml">
<xsl:template match="bk:book">
<div class="book">
<h2><xsl:value-of select="bk:title"/></h2>
<p>by <xsl:value-of select="bk:author"/></p>
</div>
</xsl:template>
</xsl:stylesheet>
SVG
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="200" height="200">
<circle cx="100" cy="100" r="50" fill="blue"/>
<text x="100" y="105" text-anchor="middle"
fill="white">DodaTech</text>
</svg>
Security Angle
Namespace injection attacks occur when user-controlled input influences namespace prefixes or URIs. An attacker might craft XML that redeclares a trusted namespace prefix to point to a malicious URI, causing parsers to misinterpret element meanings. Durga Antivirus Pro validates namespace URIs against an allowlist during XML threat signature processing, rejecting any document that uses unapproved namespace declarations. Always verify namespace declarations when processing untrusted XML.
Common Mistakes
1. Confusing the namespace URI with a URL
The namespace URI http://example.com/ns does not need to be a real web page. It is just a unique identifier string. Browsing to it may return 404.
2. Forgetting that unprefixed attributes are never in a namespace
Even inside a default namespace, attribute="value" is in no namespace. Only explicitly prefixed attributes like ns:attr="value" are namespaced.
3. Trying to use //title with namespaced XML
If the XML uses a default namespace, //title won't match. You need //ns:title with the namespace prefix mapped.
4. Redeclaring the same prefix to different URIs
This is valid but extremely confusing. Never redeclare a prefix to point to a different URI in the same document.
Practice Questions
What is the purpose of a namespace URI in XML? To uniquely identify a vocabulary of element and attribute names, preventing collisions when combining XML from different sources.
What is the difference between default and prefixed namespaces? Default namespaces apply to all unqualified descendant elements. Prefixed namespaces require an explicit prefix on every element.
Are unprefixed attributes affected by a default namespace? No. Unprefixed attributes are always in no namespace, regardless of any default namespace declaration.
Challenge: Create an XML document that combines two namespaces — one for book metadata (title, author, ISBN) and one for inventory data (warehouse, stock level, reorder threshold) — then write an XPath query that extracts only the inventory information.
FAQ
Try It Yourself
Query namespaced XML with xmllint:
# Extract titles from namespaced XML
xmllint --shell library.xml <<< "xpath //bk:title"
# Expected output depends on namespace registration
# Use --ns option to register namespace prefixes:
xmllint --ns bk=http://books.example.com/ns --xpath "//bk:title/text()" library.xml
Python namespace handling:
from lxml import etree
# Parse and register namespaces
tree = etree.parse("library.xml")
root = tree.getroot()
# Get all namespaces used in the document
nsmap = root.nsmap
print("Namespaces found:", nsmap)
# Register all namespaces for XPath
for prefix, uri in nsmap.items():
etree.register_namespace(prefix or "default", uri)
# Expected output:
# Namespaces found: {'bk': 'http://books.example.com/ns', ...}
What's Next
| Tutorial | What You'll Learn |
|---|---|
| XML Basics — Complete Guide | Foundational XML concepts |
| XPath Explained — Querying XML | Navigate XML documents with path expressions |
| XML Schema Datatypes | Advanced XSD datatypes and validation |
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro. Updated 2026-06-23.
What's Next
Congratulations on completing this XML Namespaces and URIs tutorial! Here's where to go from here:
- Practice daily — Consistency is more important than long study sessions
- Build a project — Combine two XML vocabularies using namespaces
- Explore related topics — Check out other XML tutorials in this category
- Join the community — Discuss with other learners and share your progress
Remember: every expert was once a beginner. Keep coding!
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro