Node XML Stream Parser
node-xml-stream-parser (current version 1.0.12) is a lightweight, fast XML/HTML stream parser designed for Node.js environments. It specializes in processing streaming XML, making it particularly suitable for tasks like parsing RSS, ATOM, or RDF feeds efficiently. The library's focus is on simplicity and performance, emitting events for `opentag`, `closetag`, `text`, `cdata`, and `instruction` as it processes the stream. It differentiates itself from more heavy-weight parsers (like `node-sax`) by offering a streamlined API and intentionally omitting support for less common XML features like comments, DOCTYPES, and ENTITY declarations, optimizing for speed and minimal overhead. It has seen consistent, though not rapid, updates, with the latest publish around 6 years ago on NPM, but GitHub activity suggests some more recent minor updates, making it a `maintenance` status.
Common errors
-
Error: Cannot find module 'node-xml-stream'
cause Attempting to `require()` or `import` the package using the incorrect name specified in the README's usage example, instead of the actual npm package name.fixChange the import statement to `require('node-xml-stream-parser')` for CommonJS or `import Parser from 'node-xml-stream-parser'` for ESM. -
TypeError: parser.on is not a function
cause The `Parser` class itself is being called like a function, or `new Parser()` was not used, resulting in an undefined or improperly initialized object that does not expose the event emitter methods.fixEnsure you instantiate the parser correctly with `let parser = new Parser();` before attempting to attach event listeners. -
Events like 'instruction' or 'cdata' are not firing for valid XML that contains them.
cause This is typically not an error but a misunderstanding of which events are emitted by the parser. While the parser supports these events, they only fire if the input XML stream actually contains the corresponding elements (e.g., `<?xml ...?>` for 'instruction' or `<![CDATA[...]]>` for 'cdata').fixVerify that your XML input correctly includes the specific XML constructs you expect to trigger these events. Also, double-check event handler registration.
Warnings
- gotcha The package name for `require` in the README example (`node-xml-stream`) is incorrect. The actual npm package to install and import is `node-xml-stream-parser`.
- gotcha This parser is designed to be lightweight and fast, intentionally ignoring comments (`<!-- -->`), `<!DOCTYPES>`, and `<!ENTITY>` declarations. If your application relies on parsing these XML features, this library will not extract them.
- gotcha Self-closing tags that do not have an empty space before the closing slash (e.g., `<tag/>` instead of `<tag />`) may behave unexpectedly if the tag name itself ends with a `/`. The parser strips the last `/` character from the tag name in such cases, which can lead to misinterpretation if your tag is genuinely named something ending with `/`.
- maintenance This project is a fork of an inactive `node-xml-stream` project, as noted in its README. While this fork has seen some updates, the `last publish` date on npm for version 1.0.12 is 6 years ago (February 10, 2020). While the GitHub repository may show more recent activity, be aware that official releases are infrequent.
Install
-
npm install node-xml-stream-parser -
yarn add node-xml-stream-parser -
pnpm add node-xml-stream-parser
Imports
- Parser
const Parser = require('node-xml-stream');import Parser from 'node-xml-stream-parser';
- parser.on
parser.addListener('opentag', handler);parser.on('opentag', (name, attrs) => { /* ... */ });
Quickstart
import { createReadStream } from 'fs';
import Parser from 'node-xml-stream-parser';
const xmlString = '<root><item attr="value">Hello</item><![CDATA[Some Cdata]]><item/></root>';
const parser = new Parser();
parser.on('opentag', (name, attrs) => {
console.log(`Open Tag: ${name}, Attributes:`, attrs);
});
parser.on('closetag', name => {
console.log(`Close Tag: ${name}`);
});
parser.on('text', text => {
if (text.trim() !== '') {
console.log(`Text: '${text.trim()}'`);
}
});
parser.on('cdata', cdata => {
console.log(`CDATA: '${cdata}'`);
});
parser.on('error', err => {
console.error('Parsing Error:', err.message);
});
parser.on('finish', () => {
console.log('XML stream parsing finished.');
});
// Option 1: Write data directly
console.log('--- Parsing from string ---');
parser.write(xmlString);
parser.end();
// Option 2: Pipe a file stream (for larger files)
// Ensure 'feed.atom' exists with valid XML content for this part to run.
// For example, create a dummy feed.atom: <feed><entry><title>Test</title></entry></feed>
const filePath = './feed.atom';
console.log(`\n--- Piping from file: ${filePath} ---`);
// Create a dummy file for demonstration
import { writeFileSync } from 'fs';
writeFileSync(filePath, '<feed><entry><title>Hello World</title><content>Some content.</content></entry></feed>');
const fileStreamParser = new Parser();
fileStreamParser.on('opentag', (name) => console.log(`[File] Open Tag: ${name}`));
fileStreamParser.on('closetag', (name) => console.log(`[File] Close Tag: ${name}`));
fileStreamParser.on('text', (text) => { if (text.trim() !== '') console.log(`[File] Text: '${text.trim()}'`); });
fileStreamParser.on('error', (err) => console.error('[File] Error:', err.message));
fileStreamParser.on('finish', () => console.log('[File] Parsing from file finished.'));
createReadStream(filePath).pipe(fileStreamParser);