A pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and XMLSerializer module.
Comprehensive XML Namespace support with namespace-aware methods, prefix handling, namespace URI resolution, and full compliance with XML Namespaces specification.
Element interface extensions that provide full namespace support for creating, accessing, and manipulating namespaced elements and attributes.
/**
* Namespace-aware methods on Element interface
*/
interface Element extends Node {
/**
* Gets attribute value by namespace URI and local name
* @param namespaceURI The namespace URI or null for no namespace
* @param localName The local name of the attribute
* @returns Attribute value or empty string if not found
*/
getAttributeNS(namespaceURI: string | null, localName: string): string;
/**
* Sets attribute value by namespace URI and qualified name
* @param namespaceURI The namespace URI or null for no namespace
* @param qualifiedName The qualified name (prefix:localName or localName)
* @param value The attribute value to set
*/
setAttributeNS(namespaceURI: string | null, qualifiedName: string, value: string): void;
/**
* Removes attribute by namespace URI and local name
* @param namespaceURI The namespace URI or null for no namespace
* @param localName The local name of the attribute
*/
removeAttributeNS(namespaceURI: string | null, localName: string): void;
/**
* Gets attribute node by namespace URI and local name
* @param namespaceURI The namespace URI or null for no namespace
* @param localName The local name of the attribute
* @returns Attr node or null if not found
*/
getAttributeNodeNS(namespaceURI: string | null, localName: string): Attr | null;
/**
* Sets attribute node with namespace support
* @param newAttr The Attr node to set
* @returns Previous Attr node or null
*/
setAttributeNodeNS(newAttr: Attr): Attr | null;
/**
* Gets elements by namespace URI and local name
* @param namespaceURI The namespace URI or "*" for any namespace
* @param localName The local name or "*" for any name
* @returns NodeList of matching elements
*/
getElementsByTagNameNS(namespaceURI: string | null, localName: string): NodeList;
/**
* Tests if attribute exists by namespace URI and local name
* @param namespaceURI The namespace URI or null for no namespace
* @param localName The local name of the attribute
* @returns true if attribute exists
*/
hasAttributeNS(namespaceURI: string | null, localName: string): boolean;
}Usage Examples:
const { DOMParser } = require('xmldom');
const parser = new DOMParser();
const doc = parser.parseFromString(`
<catalog xmlns="http://example.com/catalog"
xmlns:product="http://example.com/product"
xmlns:pricing="http://example.com/pricing">
<product:item product:id="123">
<product:name>Widget</product:name>
<pricing:price pricing:currency="USD">29.99</pricing:price>
</product:item>
</catalog>
`, 'text/xml');
const item = doc.getElementsByTagNameNS('http://example.com/product', 'item').item(0);
// Get namespaced attributes
const productId = item.getAttributeNS('http://example.com/product', 'id');
console.log(productId); // "123"
// Set namespaced attributes
item.setAttributeNS('http://example.com/product', 'product:status', 'active');
item.setAttributeNS('http://example.com/pricing', 'pricing:discount', '10%');
// Check existence of namespaced attributes
console.log(item.hasAttributeNS('http://example.com/product', 'status')); // true
console.log(item.hasAttributeNS('http://example.com/product', 'missing')); // false
// Get child elements by namespace
const productElements = item.getElementsByTagNameNS('http://example.com/product', '*');
console.log(productElements.length); // Elements in product namespace
const priceElements = item.getElementsByTagNameNS('http://example.com/pricing', 'price');
console.log(priceElements.item(0).textContent); // "29.99"
// Remove namespaced attribute
item.removeAttributeNS('http://example.com/pricing', 'discount');Document interface extensions for creating namespaced elements, attributes, and querying by namespace.
/**
* Namespace-aware methods on Document interface
*/
interface Document extends Node {
/**
* Creates element with namespace URI and qualified name
* @param namespaceURI The namespace URI or null for no namespace
* @param qualifiedName The qualified name (prefix:localName or localName)
* @returns New Element with specified namespace
*/
createElementNS(namespaceURI: string | null, qualifiedName: string): Element;
/**
* Creates attribute with namespace URI and qualified name
* @param namespaceURI The namespace URI or null for no namespace
* @param qualifiedName The qualified name (prefix:localName or localName)
* @returns New Attr with specified namespace
*/
createAttributeNS(namespaceURI: string | null, qualifiedName: string): Attr;
/**
* Gets elements by namespace URI and local name from entire document
* @param namespaceURI The namespace URI or "*" for any namespace
* @param localName The local name or "*" for any name
* @returns NodeList of matching elements
*/
getElementsByTagNameNS(namespaceURI: string | null, localName: string): NodeList;
}Usage Examples:
const { DOMParser } = require('xmldom');
const parser = new DOMParser();
const doc = parser.parseFromString('<root></root>', 'text/xml');
// Create namespaced elements
const catalogNS = 'http://example.com/catalog';
const productNS = 'http://example.com/product';
const catalog = doc.createElementNS(catalogNS, 'catalog');
const product = doc.createElementNS(productNS, 'product:item');
const name = doc.createElementNS(productNS, 'product:name');
// Create namespaced attributes
const idAttr = doc.createAttributeNS(productNS, 'product:id');
idAttr.value = 'P001';
const statusAttr = doc.createAttributeNS(catalogNS, 'status');
statusAttr.value = 'active';
// Build document structure
name.appendChild(doc.createTextNode('Test Product'));
product.appendChild(name);
product.setAttributeNodeNS(idAttr);
catalog.appendChild(product);
catalog.setAttributeNodeNS(statusAttr);
// Replace document element
doc.replaceChild(catalog, doc.documentElement);
// Query by namespace
const productItems = doc.getElementsByTagNameNS(productNS, 'item');
console.log(productItems.length); // 1
const allProductElements = doc.getElementsByTagNameNS(productNS, '*');
console.log(allProductElements.length); // 2 (item and name)
// Verify namespace properties
console.log(product.namespaceURI); // "http://example.com/product"
console.log(product.localName); // "item"
console.log(product.prefix); // "product"
console.log(product.nodeName); // "product:item"All nodes with namespace support provide properties for accessing namespace information.
/**
* Namespace properties on Node interface
*/
interface Node {
/**
* The namespace URI of the node, or null if unspecified
*/
readonly namespaceURI: string | null;
/**
* The namespace prefix of the node, or null if unspecified
*/
prefix: string | null;
/**
* The local name of the node (without namespace prefix)
*/
readonly localName: string | null;
}Usage Examples:
const { DOMParser } = require('xmldom');
const parser = new DOMParser();
const doc = parser.parseFromString(`
<root xmlns:ns1="http://example.com/ns1"
xmlns:ns2="http://example.com/ns2">
<ns1:element ns2:attribute="value">
<ns1:child>content</ns1:child>
</ns1:element>
</root>
`, 'text/xml');
const element = doc.getElementsByTagNameNS('http://example.com/ns1', 'element').item(0);
// Access namespace properties
console.log(element.namespaceURI); // "http://example.com/ns1"
console.log(element.prefix); // "ns1"
console.log(element.localName); // "element"
console.log(element.nodeName); // "ns1:element"
// Check attribute namespace
const attr = element.getAttributeNodeNS('http://example.com/ns2', 'attribute');
console.log(attr.namespaceURI); // "http://example.com/ns2"
console.log(attr.prefix); // "ns2"
console.log(attr.localName); // "attribute"
console.log(attr.name); // "ns2:attribute"
// Modify prefix (changes nodeName but not namespaceURI)
element.prefix = 'changed';
console.log(element.nodeName); // "changed:element"
console.log(element.namespaceURI); // Still "http://example.com/ns1"Advanced namespace resolution methods for looking up namespace URIs and testing default namespaces.
/**
* DOM Level 3 namespace lookup methods on Node interface
*/
interface Node {
/**
* Tests if given namespace URI is the default namespace
* @param namespaceURI The namespace URI to test
* @returns true if it's the default namespace
*/
isDefaultNamespace(namespaceURI: string | null): boolean;
/**
* Looks up namespace URI for given prefix
* @param prefix The namespace prefix to look up, or null for default namespace
* @returns The namespace URI or null if not found
*/
lookupNamespaceURI(prefix: string | null): string | null;
}Usage Examples:
const { DOMParser } = require('xmldom');
const parser = new DOMParser();
const doc = parser.parseFromString(`
<root xmlns="http://example.com/default"
xmlns:ns1="http://example.com/ns1"
xmlns:ns2="http://example.com/ns2">
<ns1:element>
<child>Default namespace content</child>
<ns2:item>NS2 content</ns2:item>
</ns1:element>
</root>
`, 'text/xml');
const element = doc.getElementsByTagNameNS('http://example.com/ns1', 'element').item(0);
const child = element.getElementsByTagName('child').item(0);
// Test default namespace
console.log(child.isDefaultNamespace('http://example.com/default')); // true
console.log(child.isDefaultNamespace('http://example.com/ns1')); // false
// Look up namespace URIs
console.log(element.lookupNamespaceURI('ns1')); // "http://example.com/ns1"
console.log(element.lookupNamespaceURI('ns2')); // "http://example.com/ns2"
console.log(element.lookupNamespaceURI(null)); // "http://example.com/default"
console.log(element.lookupNamespaceURI('undefined')); // nullNamedNodeMap (attribute collections) provides namespace-aware methods for managing attributes.
/**
* Namespace-aware methods on NamedNodeMap interface
*/
interface NamedNodeMap {
/**
* Gets named item by namespace URI and local name
* @param namespaceURI The namespace URI or null for no namespace
* @param localName The local name of the item
* @returns Node or null if not found
*/
getNamedItemNS(namespaceURI: string | null, localName: string): Node | null;
/**
* Sets named item with namespace support
* @param arg The Node to set
* @returns Previous Node or null
*/
setNamedItemNS(arg: Node): Node | null;
/**
* Removes named item by namespace URI and local name
* @param namespaceURI The namespace URI or null for no namespace
* @param localName The local name of the item
* @returns Removed Node
*/
removeNamedItemNS(namespaceURI: string | null, localName: string): Node;
}Usage Examples:
const { DOMParser } = require('xmldom');
const parser = new DOMParser();
const doc = parser.parseFromString('<root></root>', 'text/xml');
const element = doc.createElement('test');
const attrs = element.attributes;
// Create namespaced attributes
const ns1Attr = doc.createAttributeNS('http://example.com/ns1', 'ns1:attr1');
ns1Attr.value = 'value1';
const ns2Attr = doc.createAttributeNS('http://example.com/ns2', 'ns2:attr2');
ns2Attr.value = 'value2';
const defaultAttr = doc.createAttribute('defaultAttr');
defaultAttr.value = 'defaultValue';
// Set attributes using NamedNodeMap
attrs.setNamedItemNS(ns1Attr);
attrs.setNamedItemNS(ns2Attr);
attrs.setNamedItem(defaultAttr);
console.log(attrs.length); // 3
// Access by namespace
const retrievedNS1 = attrs.getNamedItemNS('http://example.com/ns1', 'attr1');
console.log(retrievedNS1.value); // "value1"
const retrievedNS2 = attrs.getNamedItemNS('http://example.com/ns2', 'attr2');
console.log(retrievedNS2.value); // "value2"
// Access default namespace attribute
const retrievedDefault = attrs.getNamedItemNS(null, 'defaultAttr');
console.log(retrievedDefault.value); // "defaultValue"
// Remove by namespace
const removed = attrs.removeNamedItemNS('http://example.com/ns1', 'attr1');
console.log(removed.value); // "value1"
console.log(attrs.length); // 2Special handling for default namespace declarations and inheritance.
// Default namespace is declared with xmlns="uri"
// Elements without prefix inherit the default namespace
// Attributes never inherit default namespace (always null unless explicitly namespaced)Usage Examples:
const { DOMParser, XMLSerializer } = require('xmldom');
const parser = new DOMParser();
const serializer = new XMLSerializer();
// Document with default namespace
const doc = parser.parseFromString(`
<catalog xmlns="http://example.com/catalog">
<product>
<name>Widget</name>
</product>
<external xmlns="http://example.com/external">
<item>External item</item>
</external>
</catalog>
`, 'text/xml');
// Elements inherit default namespace
const catalog = doc.documentElement;
console.log(catalog.namespaceURI); // "http://example.com/catalog"
console.log(catalog.localName); // "catalog"
console.log(catalog.prefix); // null
const product = catalog.getElementsByTagName('product').item(0);
console.log(product.namespaceURI); // "http://example.com/catalog" (inherited)
const external = catalog.getElementsByTagName('external').item(0);
console.log(external.namespaceURI); // "http://example.com/external" (redeclared)
const item = external.getElementsByTagName('item').item(0);
console.log(item.namespaceURI); // "http://example.com/external" (inherited)
// Create new document with default namespace
const newDoc = parser.parseFromString('<root></root>', 'text/xml');
const catalogElement = newDoc.createElementNS('http://example.com/catalog', 'catalog');
catalogElement.setAttribute('xmlns', 'http://example.com/catalog');
const productElement = newDoc.createElementNS('http://example.com/catalog', 'product');
catalogElement.appendChild(productElement);
newDoc.replaceChild(catalogElement, newDoc.documentElement);
console.log(serializer.serializeToString(newDoc));
// Produces proper default namespace declarationInstall with Tessl CLI
npx tessl i tessl/npm-xmldom