A pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and XMLSerializer module
Complete W3C DOM Level 2 Core implementation for creating, accessing, and modifying document trees. Provides full node hierarchy with standard manipulation methods.
Root document node that serves as the factory for creating other nodes and provides document-wide query methods.
/**
* Represents the root of a DOM tree
* Provides factory methods for creating nodes and document-wide queries
*/
class Document extends Node {
readonly nodeType: 9; // DOCUMENT_NODE
readonly nodeName: '#document';
readonly contentType: string; // MIME type used during parsing
readonly type: 'html' | 'xml'; // Document type
readonly implementation: DOMImplementation;
readonly doctype: DocumentType | null;
readonly documentElement: Element | null; // Root element
// Node creation methods
createElement(tagName: string): Element;
createElementNS(namespace: string | null, qualifiedName: string): Element;
createTextNode(data: string): Text;
createComment(data: string): Comment;
createCDATASection(data: string): CDATASection;
createAttribute(localName: string): Attr;
createAttributeNS(namespace: string | null, qualifiedName: string): Attr;
createDocumentFragment(): DocumentFragment;
createProcessingInstruction(target: string, data: string): ProcessingInstruction;
// Query methods
getElementById(elementId: string): Element | null;
getElementsByTagName(qualifiedName: string): LiveNodeList<Element>;
getElementsByTagNameNS(namespaceURI: string | null, localName: string): LiveNodeList<Element>;
getElementsByClassName(classNames: string): LiveNodeList<Element>;
// Node import
importNode<T extends Node>(node: T, deep?: boolean): T;
}Usage Examples:
const { DOMParser } = require('@xmldom/xmldom');
const parser = new DOMParser();
const doc = parser.parseFromString('<root></root>', 'text/xml');
// Create elements
const element = doc.createElement('item');
element.setAttribute('id', '123');
element.textContent = 'Item content';
// Create elements with namespaces
const nsElement = doc.createElementNS('http://example.com', 'ns:item');
// Query elements
const root = doc.documentElement;
const items = doc.getElementsByTagName('item');
const itemById = doc.getElementById('123');
// Create other node types
const textNode = doc.createTextNode('Hello world');
const comment = doc.createComment('This is a comment');
const cdata = doc.createCDATASection('Raw content');Represents XML/HTML elements with attributes and child elements.
/**
* Represents an element in the DOM tree
* Provides attribute manipulation and element-specific query methods
*/
class Element extends Node {
readonly nodeType: 1; // ELEMENT_NODE
readonly tagName: string; // Uppercase qualified name
readonly attributes: NamedNodeMap;
// Attribute methods
getAttribute(qualifiedName: string): string | null;
getAttributeNS(namespace: string | null, localName: string): string | null;
getAttributeNames(): string[];
getAttributeNode(qualifiedName: string): Attr | null;
getAttributeNodeNS(namespace: string | null, localName: string): Attr | null;
setAttribute(qualifiedName: string, value: string): void;
setAttributeNS(namespace: string | null, qualifiedName: string, value: string): void;
setAttributeNode(attr: Attr): Attr | null;
setAttributeNodeNS(attr: Attr): Attr | null;
removeAttribute(qualifiedName: string): void;
removeAttributeNS(namespace: string | null, localName: string): void;
removeAttributeNode(attr: Attr): Attr;
hasAttribute(qualifiedName: string): boolean;
hasAttributeNS(namespace: string | null, localName: string): boolean;
hasAttributes(): boolean;
// Element query methods
getElementsByTagName(qualifiedName: string): LiveNodeList<Element>;
getElementsByTagNameNS(namespaceURI: string | null, localName: string): LiveNodeList<Element>;
getElementsByClassName(classNames: string): LiveNodeList<Element>;
// Utility methods
getQualifiedName(): string;
}Usage Examples:
// Working with attributes
element.setAttribute('class', 'primary');
element.setAttribute('data-id', '42');
const className = element.getAttribute('class'); // 'primary'
// Namespace attributes
element.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', '#target');
const href = element.getAttributeNS('http://www.w3.org/1999/xlink', 'href');
// Check attributes
const hasClass = element.hasAttribute('class'); // true
const attributeNames = element.getAttributeNames(); // ['class', 'data-id', 'xlink:href']
// Query child elements
const children = element.getElementsByTagName('child');
const byClass = element.getElementsByClassName('highlight');Abstract base class for all DOM nodes providing core tree manipulation methods.
/**
* Abstract base class for all DOM nodes
* Provides core tree navigation and manipulation functionality
*/
class Node {
// Node type constants
static readonly ELEMENT_NODE: 1;
static readonly ATTRIBUTE_NODE: 2;
static readonly TEXT_NODE: 3;
static readonly CDATA_SECTION_NODE: 4;
static readonly PROCESSING_INSTRUCTION_NODE: 7;
static readonly COMMENT_NODE: 8;
static readonly DOCUMENT_NODE: 9;
static readonly DOCUMENT_TYPE_NODE: 10;
static readonly DOCUMENT_FRAGMENT_NODE: 11;
// Core properties
readonly nodeType: number;
readonly nodeName: string;
nodeValue: string | null;
readonly parentNode: Node | null;
readonly childNodes: NodeList;
readonly firstChild: Node | null;
readonly lastChild: Node | null;
readonly previousSibling: Node | null;
readonly nextSibling: Node | null;
readonly ownerDocument: Document | null;
readonly namespaceURI: string | null;
prefix: string | null;
readonly localName: string | null;
textContent: string | null;
readonly baseURI: string;
readonly isConnected: boolean;
// Location tracking (if locator enabled)
lineNumber?: number;
columnNumber?: number;
// Tree manipulation
appendChild(node: Node): Node;
insertBefore(node: Node, child: Node | null): Node;
removeChild(child: Node): Node;
replaceChild(node: Node, child: Node): Node;
cloneNode(deep?: boolean): Node;
// Tree queries
hasChildNodes(): boolean;
contains(other: Node | null | undefined): boolean;
getRootNode(options?: { composed?: boolean }): Node;
// Node comparison
isEqualNode(other: Node): boolean;
isSameNode(other: Node): boolean;
compareDocumentPosition(other: Node): number;
// Namespace methods
lookupNamespaceURI(prefix: string | null): string | null;
lookupPrefix(namespace: string | null): string | null;
isDefaultNamespace(namespace: string | null): boolean;
// Text normalization
normalize(): void;
// Legacy method
isSupported(feature: string, version: string): true;
}Usage Examples:
// Tree manipulation
const parent = doc.createElement('parent');
const child1 = doc.createElement('child1');
const child2 = doc.createElement('child2');
parent.appendChild(child1);
parent.insertBefore(child2, child1); // child2 is now first
// Node traversal
const firstChild = parent.firstChild;
const nextSibling = firstChild.nextSibling;
const allChildren = parent.childNodes;
// Node cloning
const shallowClone = parent.cloneNode(false); // No children
const deepClone = parent.cloneNode(true); // With all descendants
// Node comparison
const isEqual = node1.isEqualNode(node2);
const isSame = node1.isSameNode(node2);Node types for handling textual content.
/**
* Abstract base class for nodes containing character data
*/
class CharacterData extends Node {
data: string; // The character data
readonly length: number; // Length of the data
appendData(data: string): void;
insertData(offset: number, data: string): void;
deleteData(offset: number, count: number): void;
replaceData(offset: number, count: number, data: string): void;
substringData(offset: number, count: number): string;
}
/**
* Represents text content in elements
*/
class Text extends CharacterData {
readonly nodeType: 3; // TEXT_NODE
readonly nodeName: '#text';
splitText(offset: number): Text;
}
/**
* Represents comments in markup
*/
class Comment extends CharacterData {
readonly nodeType: 8; // COMMENT_NODE
readonly nodeName: '#comment';
}
/**
* Represents CDATA sections in XML
*/
class CDATASection extends Text {
readonly nodeType: 4; // CDATA_SECTION_NODE
readonly nodeName: '#cdata-section';
}
/**
* Represents processing instructions
*/
class ProcessingInstruction extends CharacterData {
readonly nodeType: 7; // PROCESSING_INSTRUCTION_NODE
readonly target: string; // PI target name
data: string; // PI data content
}Usage Examples:
// Working with text nodes
const textNode = doc.createTextNode('Hello world');
textNode.appendData(' - more text');
textNode.replaceData(0, 5, 'Hi'); // 'Hi world - more text'
// Split text nodes
const secondPart = textNode.splitText(5); // Splits at position 5
// CDATA sections
const cdata = doc.createCDATASection('<script>alert("hi")</script>');
element.appendChild(cdata);
// Processing instructions
const pi = doc.createProcessingInstruction('xml-stylesheet', 'type="text/css" href="style.css"');/**
* Represents an attribute node
*/
class Attr extends Node {
readonly nodeType: 2; // ATTRIBUTE_NODE
readonly name: string; // Attribute name
readonly namespaceURI: string | null;
readonly prefix: string | null;
readonly ownerElement: Element | null;
readonly specified: true; // Always true in this implementation
value: string; // Attribute value
}/**
* Array-like collection of nodes
*/
class NodeList<T extends Node = Node> implements Iterable<T> {
readonly length: number;
item(index: number): T | null;
[index: number]: T;
[Symbol.iterator](): Iterator<T>;
}
/**
* Live collection that updates automatically with DOM changes
*/
interface LiveNodeList<T extends Node = Node> extends NodeList<T> {}
/**
* Collection of attributes accessible by name
*/
class NamedNodeMap implements Iterable<Attr> {
readonly length: number;
getNamedItem(qualifiedName: string): Attr | null;
getNamedItemNS(namespace: string | null, localName: string): Attr | null;
setNamedItem(attr: Attr): Attr | null;
setNamedItemNS(attr: Attr): Attr | null;
removeNamedItem(qualifiedName: string): Attr;
removeNamedItemNS(namespace: string | null, localName: string): Attr;
item(index: number): Attr | null;
[index: number]: Attr;
[Symbol.iterator](): Iterator<Attr>;
}/**
* Represents an entity node (legacy DOM feature)
* Primarily used in DTD processing and rarely encountered in modern XML
*/
class Entity extends Node {
readonly nodeType: 6; // ENTITY_NODE
readonly nodeName: string;
readonly publicId: string | null;
readonly systemId: string | null;
readonly notationName: string | null;
}
/**
* Represents an entity reference node (legacy DOM feature)
* Used to represent entity references in XML documents
*/
class EntityReference extends Node {
readonly nodeType: 5; // ENTITY_REFERENCE_NODE
readonly nodeName: string; // The entity name
}
/**
* Represents a notation node (legacy DOM feature)
* Used in DTD declarations to define data formats
*/
class Notation extends Node {
readonly nodeType: 12; // NOTATION_NODE
readonly nodeName: string;
readonly publicId: string | null;
readonly systemId: string | null;
}Usage Examples:
const { DOMParser, Entity, EntityReference, Notation } = require('@xmldom/xmldom');
// These node types are typically created during DTD processing
// and are rarely used in modern XML applications
function checkNodeType(node) {
switch (node.nodeType) {
case Entity.ENTITY_NODE:
console.log(`Entity: ${node.nodeName}`);
break;
case EntityReference.ENTITY_REFERENCE_NODE:
console.log(`Entity Reference: ${node.nodeName}`);
break;
case Notation.NOTATION_NODE:
console.log(`Notation: ${node.nodeName}`);
break;
}
}/**
* Factory for creating new documents and document types
*/
class DOMImplementation {
constructor();
createDocument(
namespaceURI: string | null,
qualifiedName: string,
doctype?: DocumentType | null
): Document;
createDocumentType(
qualifiedName: string,
publicId?: string,
systemId?: string
): DocumentType;
createHTMLDocument(title?: string | false): Document;
// Deprecated but always returns true
hasFeature(feature: string, version?: string): true;
}
/**
* Represents a document type declaration
*/
class DocumentType extends Node {
readonly nodeType: 10; // DOCUMENT_TYPE_NODE
readonly name: string;
readonly publicId: string;
readonly systemId: string;
readonly internalSubset: string;
}
/**
* Lightweight document container
*/
class DocumentFragment extends Node {
readonly nodeType: 11; // DOCUMENT_FRAGMENT_NODE
readonly ownerDocument: Document;
getElementById(elementId: string): Element | null;
}Usage Examples:
// Create new documents
const impl = new DOMImplementation();
const doctype = impl.createDocumentType('html', '', '');
const htmlDoc = impl.createDocument('http://www.w3.org/1999/xhtml', 'html', doctype);
// Document fragments for efficient DOM construction
const fragment = doc.createDocumentFragment();
for (let i = 0; i < 10; i++) {
const item = doc.createElement('item');
item.textContent = `Item ${i}`;
fragment.appendChild(item);
}
parent.appendChild(fragment); // Adds all items at onceInstall with Tessl CLI
npx tessl i tessl/npm-xmldom--xmldom