How xml2js Converts XML Trees to JavaScript Objects

The xml2js module converts XML markup into JavaScript object graphs by leveraging an event-driven SAX parser combined with an internal state stack. Instead of building a resource-heavy Document Object Model (DOM) in memory, xml2js streams the XML string sequentially, identifies structural boundaries, and dynamically constructs nested JavaScript objects, arrays, and primitive values based on predefined parsing rules.

The SAX-Based Parsing Pipeline

At its core, xml2js relies on sax-js, a pure JavaScript SAX (Simple API for XML) parser. The conversion process is stream-oriented and event-driven:

  1. Tokenization: As the parser reads the input XML string, it breaks the text into distinct lexical tokens (such as element opening tags, attributes, text nodes, and closing tags).
  2. Event Emission: When the tokenizer detects these boundaries, it emits specific events, primarily opentag, text, cdata, and closetag.
  3. Listener Processing: The xml2js parser listens to these events to assemble the target JavaScript structure incrementally.

Managing Hierarchy with the Stack Model

To convert flat streaming events into a multi-dimensional object tree, xml2js maintains an execution stack:

Property Mapping and Array Normalization

Because XML elements can repeat under the same parent while JavaScript object keys must be unique, xml2js applies specific structural rules:

Final Graph Generation

Once the root element’s closing tag is processed and the stack is empty, the parser finishes building the object tree. The resulting native JavaScript graph mirrors the original XML hierarchy and is returned asynchronously via a Promise or a callback function.