These five npm packages handle XML parsing, validation, and generation in JavaScript and Node.js environments. @xmldom/xmldom provides a W3C-compliant DOM implementation that works in both browsers and Node.js. fast-xml-parser focuses on high-performance parsing and validation with flexible output formats. libxmljs offers native bindings to libxml2 with full XPath and schema validation support but requires compilation. xml2js converts XML to JavaScript objects and vice versa with a mature, stable API. xmlbuilder specializes in programmatically building XML documents with a chainable interface. Each serves different needs based on environment constraints, performance requirements, and feature needs.
Working with XML in JavaScript applications requires choosing the right tool for your specific needs. The five packages we are comparing β @xmldom/xmldom, fast-xml-parser, libxmljs, xml2js, and xmlbuilder β each take different approaches to XML handling. Let's examine how they solve common problems.
@xmldom/xmldom implements the W3C DOM specification, giving you a familiar document tree structure.
import { DOMParser } from '@xmldom/xmldom';
const parser = new DOMParser();
const doc = parser.parseFromString('<root><item id="1">Hello</item></root>', 'text/xml');
const item = doc.getElementsByTagName('item')[0];
console.log(item.getAttribute('id')); // "1"
console.log(item.textContent); // "Hello"
fast-xml-parser parses XML to JavaScript objects with high performance.
import { XMLParser } from 'fast-xml-parser';
const parser = new XMLParser();
const result = parser.parse('<root><item id="1">Hello</item></root>');
console.log(result.root.item['@_id']); // "1"
console.log(result.root.item['#text']); // "Hello"
libxmljs uses native libxml2 bindings for full XML feature support.
import libxmljs from 'libxmljs';
const doc = libxmljs.parseXmlString('<root><item id="1">Hello</item></root>');
const item = doc.get('//item');
console.log(item.attr('id').value()); // "1"
console.log(item.text()); // "Hello"
xml2js converts XML to plain JavaScript objects.
import { parseStringPromise } from 'xml2js';
const result = await parseStringPromise('<root><item id="1">Hello</item></root>');
console.log(result.root.item[0].$.id); // "1"
console.log(result.root.item[0]._); // "Hello"
xmlbuilder does not parse XML β it only builds XML documents. For parsing, you would need to combine it with another library.
// xmlbuilder is for building only, not parsing
// You would use it alongside a parser like:
import { create } from 'xmlbuilder';
// Parsing would require @xmldom/xmldom or fast-xml-parser
@xmldom/xmldom can serialize DOM trees back to XML strings.
import { DOMParser, XMLSerializer } from '@xmldom/xmldom';
const parser = new DOMParser();
const doc = parser.parseFromString('<root/>', 'text/xml');
const item = doc.createElement('item');
item.setAttribute('id', '1');
item.textContent = 'Hello';
doc.documentElement.appendChild(item);
const serializer = new XMLSerializer();
const xmlString = serializer.serializeToString(doc);
// <root><item id="1">Hello</item></root>
fast-xml-parser includes XML building capabilities alongside parsing.
import { XMLBuilder } from 'fast-xml-parser';
const builder = new XMLBuilder({ ignoreAttributes: false });
const obj = {
root: {
item: {
'@_id': '1',
'#text': 'Hello'
}
}
};
const xmlString = builder.build(obj);
// <root><item id="1">Hello</item></root>
libxmljs can create XML documents programmatically with native performance.
import libxmljs from 'libxmljs';
const doc = new libxmljs.Document();
const root = doc.node('root');
const item = root.node('item').attr('id', '1').text('Hello');
const xmlString = doc.toString();
// <root><item id="1">Hello</item></root>
xml2js includes a Builder class for converting objects back to XML.
import { Builder } from 'xml2js';
const builder = new Builder();
const obj = {
root: {
item: {
$: { id: '1' },
_: 'Hello'
}
}
};
const xmlString = builder.buildObject(obj);
// <root><item id="1">Hello</item></root>
xmlbuilder specializes in XML generation with a clean chainable API.
import { create } from 'xmlbuilder';
const xml = create({ version: '1.0' })
.ele('root')
.ele('item').att('id', '1').txt('Hello')
.end({ pretty: true });
// <?xml version="1.0"?>
// <root>
// <item id="1">Hello</item>
// </root>
@xmldom/xmldom supports standard DOM methods but has limited XPath support.
import { DOMParser } from '@xmldom/xmldom';
const doc = new DOMParser().parseFromString('<root><item id="1"/><item id="2"/></root>', 'text/xml');
const items = doc.getElementsByTagName('item');
console.log(items.length); // 2
// XPath requires additional setup or libraries
fast-xml-parser does not support XPath β you query the resulting JavaScript object.
import { XMLParser } from 'fast-xml-parser';
const parser = new XMLParser();
const result = parser.parse('<root><item id="1"/><item id="2"/></root>');
const items = Array.isArray(result.root.item) ? result.root.item : [result.root.item];
console.log(items.length); // 2
libxmljs has full XPath support built in.
import libxmljs from 'libxmljs';
const doc = libxmljs.parseXmlString('<root><item id="1"/><item id="2"/></root>');
const items = doc.find('//item[@id]');
console.log(items.length); // 2
console.log(items[0].attr('id').value()); // "1"
xml2js does not support XPath β you navigate the JavaScript object structure.
import { parseStringPromise } from 'xml2js';
const result = await parseStringPromise('<root><item id="1"/><item id="2"/></root>');
const items = result.root.item;
console.log(items.length); // 2
console.log(items[0].$.id); // "1"
xmlbuilder does not support querying β it is for building only.
// xmlbuilder has no query capabilities
// Use it with a parser library for full XML workflow
@xmldom/xmldom runs everywhere β browsers and Node.js β with no native dependencies.
// Works identically in browser and Node.js
import { DOMParser } from '@xmldom/xmldom';
// No compilation needed, pure JavaScript
fast-xml-parser is pure JavaScript with optimized performance for large files.
// Pure JS, no native dependencies
import { XMLParser } from 'fast-xml-parser';
// Known for speed in benchmark tests
libxmljs requires native compilation and Node.js only.
// Requires node-gyp compilation
import libxmljs from 'libxmljs';
// Will NOT work in browsers
// May have installation issues on some platforms
xml2js is pure JavaScript and works in both environments.
// Pure JS, browser and Node.js compatible
import { parseStringPromise } from 'xml2js';
// Mature and stable
xmlbuilder is pure JavaScript with broad environment support.
// Pure JS, works everywhere
import { create } from 'xmlbuilder';
// No compilation required
@xmldom/xmldom has limited validation β it parses but does not validate against schemas.
import { DOMParser } from '@xmldom/xmldom';
const parser = new DOMParser();
// No built-in schema validation
// Will parse invalid XML without throwing errors in some cases
const doc = parser.parseFromString('<root><item>', 'text/xml');
fast-xml-parser includes optional validation features.
import { XMLParser, XMLValidator } from 'fast-xml-parser';
const isValid = XMLValidator.validate('<root><item/></root>');
console.log(isValid); // true if valid
const parser = new XMLParser({ ignoreAttributes: false });
libxmljs has full XML Schema and DTD validation support.
import libxmljs from 'libxmljs';
const doc = libxmljs.parseXmlString('<root><item/></root>');
// Can validate against XSD schemas
// Full validation capabilities from libxml2
xml2js does not include validation β it assumes input is valid XML.
import { parseStringPromise } from 'xml2js';
// No validation built in
// Will throw on malformed XML but no schema validation
try {
await parseStringPromise('<root><item>');
} catch (err) {
console.error(err); // Parse error
}
xmlbuilder does not validate β it generates XML structures.
import { create } from 'xmlbuilder';
// No validation β builds whatever structure you define
const xml = create().ele('root').ele('item').end();
You are building an XML editor that runs in the browser with DOM manipulation.
@xmldom/xmldomimport { DOMParser, XMLSerializer } from '@xmldom/xmldom';
const parser = new DOMParser();
const doc = parser.parseFromString(xmlString, 'text/xml');
// Use standard DOM methods like getElementById, appendChild, etc.
You need to process thousands of XML files quickly in Node.js.
fast-xml-parserimport { XMLParser } from 'fast-xml-parser';
const parser = new XMLParser();
const results = files.map(file => parser.parse(file.content));
// Fast parsing for bulk operations
You need to query XML documents with complex XPath expressions.
libxmljsimport libxmljs from 'libxmljs';
const doc = libxmljs.parseXmlString(xmlString);
const nodes = doc.find('//book[author="Smith"]');
// Powerful XPath queries
You receive XML API responses and want JavaScript objects.
xml2jsimport { parseStringPromise } from 'xml2js';
const data = await parseStringPromise(apiResponse);
// Easy access: data.root.item[0].$.id
You need to create XML documents programmatically for reports.
xmlbuilderimport { create } from 'xmlbuilder';
const report = create({ version: '1.0' })
.ele('report')
.ele('header').txt('Monthly Report')
.ele('data').dat(new Date())
.end({ pretty: true });
| Package | Environment | Native Deps | XPath | Validation | Build XML | Parse XML |
|---|---|---|---|---|---|---|
@xmldom/xmldom | Browser + Node | β | Limited | β | β (serialize) | β (DOM) |
fast-xml-parser | Browser + Node | β | β | β | β | β |
libxmljs | Node only | β | β | β | β | β |
xml2js | Browser + Node | β | β | β | β | β |
xmlbuilder | Browser + Node | β | β | β | β | β |
As of current documentation, none of these five packages are officially deprecated. However:
libxmljs requires native compilation which can cause installation issues on some platforms and prevents browser usage.xml2js is mature but development has slowed β it is stable but not actively adding new features.@xmldom/xmldom is the maintained fork of the original xmldom package (which is deprecated).Think in terms of environment, features, and workflow:
libxmljs, choose from the pure JS options.libxmljs is your only full-featured option.fast-xml-parser leads in performance benchmarks.@xmldom/xmldom provides W3C DOM APIs.xml2js is stable and straightforward.xmlbuilder has the cleanest building API.Final Thought: XML processing in JavaScript has matured significantly. Choose based on your specific constraints β environment compatibility, feature requirements, and performance needs β rather than trying to find one solution that does everything.
Choose xmlbuilder if your primary need is generating XML documents programmatically. It excels when you need to build complex XML structures with a clean, chainable API rather than parsing existing XML.
Choose @xmldom/xmldom if you need a pure JavaScript DOM implementation that works identically in browsers and Node.js. It is ideal when you want W3C DOM compatibility without native dependencies, especially for isomorphic applications or when working with existing DOM-based code.
Choose fast-xml-parser if performance is your top priority and you need flexible parsing options including validation. It works well for high-volume XML processing where speed matters and you want both parsing and building capabilities in one package.
Choose libxmljs if you need full XML feature support including XPath queries and schema validation in a Node.js-only environment. Avoid it for browser projects or when you cannot handle native module compilation requirements.
Choose xml2js if you want to convert XML directly to JavaScript objects for easy manipulation. It is best for projects where you treat XML as data rather than a document structure and need a stable, well-tested solution.
An XML builder for node.js similar to java-xmlbuilder.
xmlbuilder2:The new release of xmlbuilder is available at xmlbuilder2! xmlbuilder2 has been redesigned from the ground up to be fully conforming to the modern DOM specification. It supports XML namespaces, provides built-in converters for multiple formats, collection functions, and more. Please see upgrading from xmlbuilder in the wiki.
New development will be focused towards xmlbuilder2; xmlbuilder will only receive critical bug fixes.
npm install xmlbuilder
var builder = require('xmlbuilder');
var xml = builder.create('root')
.ele('xmlbuilder')
.ele('repo', {'type': 'git'}, 'git://github.com/oozcitak/xmlbuilder-js.git')
.end({ pretty: true});
console.log(xml);
will result in:
<?xml version="1.0"?>
<root>
<xmlbuilder>
<repo type="git">git://github.com/oozcitak/xmlbuilder-js.git</repo>
</xmlbuilder>
</root>
It is also possible to convert objects into nodes:
var builder = require('xmlbuilder');
var obj = {
root: {
xmlbuilder: {
repo: {
'@type': 'git', // attributes start with @
'#text': 'git://github.com/oozcitak/xmlbuilder-js.git' // text node
}
}
}
};
var xml = builder.create(obj).end({ pretty: true});
console.log(xml);
If you need to do some processing:
var builder = require('xmlbuilder');
var root = builder.create('squares');
root.com('f(x) = x^2');
for(var i = 1; i <= 5; i++)
{
var item = root.ele('data');
item.att('x', i);
item.att('y', i * i);
}
var xml = root.end({ pretty: true});
console.log(xml);
This will result in:
<?xml version="1.0"?>
<squares>
<!-- f(x) = x^2 -->
<data x="1" y="1"/>
<data x="2" y="4"/>
<data x="3" y="9"/>
<data x="4" y="16"/>
<data x="5" y="25"/>
</squares>
See the wiki for details and examples for more complex examples.