Saxes Streaming XML Parser
Saxes is an evented, streaming XML parser for JavaScript, currently at version 6.0.0. It is a modern, stricter, and significantly faster fork of the original `sax` library, designed primarily for Node.js environments (requiring Node.js >=12.22.7) but also functional in browsers. Its core differentiator is a strong adherence to XML 1.0/1.1 and Namespaces in XML 1.0/1.1 well-formedness rules, unlike `sax` which tolerates malformed structures. This makes `saxes` unsuitable for HTML or pseudo-XML parsing, as it will explicitly report well-formedness errors. While it is a non-validating parser, it aims to catch all malformed constructs outside of thorough DTD validation. `saxes` does not include a `Stream` API, a notable departure from its `sax` predecessor, and its `onerror` handler defaults to throwing errors, which can be overridden. The project is actively maintained, with a focus on performance and strict conformance to XML specifications.
Common errors
-
XML Parsing Error: Malformed XML: unexpected end of document
cause The input XML string is not well-formed according to XML 1.0/1.1 specifications. Saxes is very strict and will reject documents that `sax` might parse.fixReview your XML input for any structural errors, unclosed tags, invalid characters, or incorrect entity usage. Ensure it's valid XML, not HTML. -
TypeError: SaxesParser is not a constructor
cause Incorrect import statement, often due to mixing CommonJS `require` with ES Module `import` syntax or attempting a default import when `SaxesParser` is a named export.fixFor ES Modules: `import { SaxesParser } from 'saxes';`. For CommonJS: `const { SaxesParser } = require('saxes');`. -
TypeError: parser.resume is not a function
cause Attempting to call `parser.resume()` after an error, a method that existed in the original `sax` library but is not present in `saxes` due to the removal of the `Stream` API and different error handling philosophy.fixHandle errors in your `parser.on('error', ...)` listener. Saxes throws errors by default; if you catch them, you typically just let the parser continue or stop processing the input, as there's no `resume` mechanism.
Warnings
- breaking Saxes is significantly stricter with XML well-formedness than its predecessor, `sax`. It will report errors for malformed XML that `sax` might silently accept. This is a deliberate design choice for compliance.
- breaking Saxes does not expose a `Stream` API. If you were relying on `sax`'s `Stream` functionality, you will need to adapt your code to use the `parser.write()` method directly with character chunks.
- gotcha The `onerror` handler in `saxes` throws errors by default. In `sax`, errors would often be emitted and require explicit `parser.error = null` and `parser.resume()` calls. This behavior change means unhandled errors will halt execution.
- gotcha Saxes is a non-validating parser. It does not thoroughly parse DTDs, meaning most malformedness errors within DTDs cannot be reported. Basic XML entities (`&`, `<`, etc.) are handled, but custom DTD-defined entities are not automatically processed.
- breaking Saxes dropped support for antiquated platforms, including Node versions older than 10 and IE11. The library is built with modern JavaScript (ES6+).
- gotcha The internal implementation and non-public API of `saxes` are subject to change without warning. The documentation explicitly advises against using anything not formally public, protected, or documented in JSDOC as public.
Install
-
npm install saxes -
yarn add saxes -
pnpm add saxes
Imports
- SaxesParser
import SaxesParser from 'saxes'; // OR const SaxesParser = require('saxes').SaxesParser;import { SaxesParser } from 'saxes'; - SaxesOptions
import { SaxesOptions } from 'saxes';import type { SaxesOptions } from 'saxes'; - CommonJS require
const saxes = require('saxes'); const parser = new saxes.SaxesParser();const { SaxesParser } = require('saxes');
Quickstart
import { SaxesParser } from 'saxes';
const xmlString = `<root>
<item id="1">Hello & World!</item>
<item id="2"><![CDATA[<tag>content</tag>]]></item>
</root>`;
const parser = new SaxesParser();
parser.on('error', (err) => {
console.error('XML Parsing Error:', err.message);
// The default onerror handler throws, so subsequent data calls might not happen if not caught.
});
parser.on('opentag', (node) => {
console.log(`Opened tag: ${node.name} with attributes:`, node.attributes);
});
parser.on('text', (text) => {
if (text.trim().length > 0) {
console.log(`Text content: '${text.trim()}'`);
}
});
parser.on('closetag', (nodeName) => {
console.log(`Closed tag: ${nodeName}`);
});
parser.on('end', () => {
console.log('Finished parsing XML.');
});
try {
parser.write(xmlString).close();
} catch (e) {
// Catch errors if the default onerror handler is active and throws
console.error('Caught error during write/close:', e.message);
}