DOM Tree Construction
Relevant source files
The following files were used as context for generating this wiki page:
DOM Tree Construction in htmlparser2 is the process of transforming a raw stream of HTML or XML data into a structured Document Object Model (DOM). While the core Parser provides a low-level callback interface to handle events like tag opening and closing, the project utilizes the domhandler library to aggregate these events into a tree structure. This modular approach allows for high-performance parsing with minimal memory allocations when needed, while still providing a standard DOM interface for complex document manipulation.
Sources: README.md:46-50, src/index.ts:31-35
Architecture and Data Flow
The construction process follows a pipeline where raw data is tokenized, parsed into high-level events, and then handled by a DOM builder. The Parser class acts as the coordinator between the Tokenizer and the provided Handler (typically DomHandler).
The data flow starts with the write or parseComplete methods, which feed the Tokenizer. The Tokenizer identifies sequences such as tag names, attributes, and text, and notifies the Parser. The Parser then enforces HTML/XML logic (like implicit tag closing) before calling the handler's methods to create DOM nodes.
Sources: src/Parser.ts:639-650, src/index.ts:31-35, src/Tokenizer.ts:681-690
Key Components
Core API Methods
The library provides two primary entry points for generating a DOM tree:
| Method | Description |
|---|---|
parseDocument(data, options) | A synchronous helper that parses a string and returns a Document node. |
createDocumentStream(callback, options) | Creates a Parser instance attached to a DomHandler for processing streaming data. |
Sources: src/index.ts:31-35, src/index.ts:46-55
The Parser Class
The Parser class handles the higher-level state management of the document, including the element stack and foreign context (SVG/MathML). It translates low-level tokenizer callbacks into structured tag and attribute events.
- Stack Management: Uses
this.stack: string[]to track open elements and ensure proper nesting. - Foreign Context: Maintains a
foreignContextstack to handle namespace-specific rules for SVG and MathML. - Case Sensitivity: In HTML mode, tag and attribute names are typically lowercased, but case adjustments are applied for SVG elements (e.g.,
altglyphbecomesaltGlyph).
Sources: src/Parser.ts:252-263, src/Parser.ts:323-345, src/Parser.ts:384-398
Parsing Logic and Constraints
Implicit Tag Closing and Opening
In HTML mode, the parser handles elements that implicitly close other open elements based on the HTML specification. For example, a <li> tag will implicitly close a currently open <li> tag.
The openImpliesClose map defines these relationships, such as tr closing tr, th, or td.
Sources: src/Parser.ts:36-79, src/Parser.ts:389-393
Configuration Options
The behavior of the DOM construction is heavily influenced by ParserOptions:
| Option | Type | Effect on DOM |
|---|---|---|
xmlMode | boolean | If true, treats the document as XML, affecting self-closing tags and CDATA. |
lowerCaseTags | boolean | Determines if tag names are normalized to lowercase. |
recognizeSelfClosing | boolean | If true, /> in HTML will close the element immediately. |
Sources: src/Parser.ts:160-199
Foreign Context Handling
The parser tracks when it enters "foreign" namespaces like SVG or MathML. When inside these contexts, standard HTML rules (like void elements) are suspended, and tag names may be adjusted to meet specific casing requirements.
Sources: src/Parser.ts:133-158, src/Parser.ts:401-408
Summary
DOM Tree Construction in htmlparser2 is a multi-stage process that prioritizes speed and flexibility. By separating the concern of tokenization from tree construction via the Handler interface, the system can either stream events for low-memory consumption or build a full tree for comprehensive document analysis. The Parser ensures technical accuracy by managing element stacks and complying with HTML/XML-specific nesting rules.
Sources: README.md:15-25, src/index.ts:31-35