XML Validation with xmllint (libxml2)
node-xmllint is an Emscripten port of libxml2's `xmllint` utility, enabling XML and XSD schema validation directly within Node.js environments and web browsers. It provides a synchronous `validateXML` function that returns an object containing an `errors` array (or null if no errors). As of version 1.0.0, the package has not seen updates in approximately 8 years, indicating it is an abandoned project. Its key differentiator was bringing the battle-tested libxml2 C validation engine to JavaScript runtimes, supporting complex XML Schema Definitions directly, unlike simpler regex-based or DOM-parser-based validation methods available at the time. It was designed to integrate with older frontend bundling tools like Browserify via `browserify-shim` for browser usage. Newer, actively maintained alternatives exist that leverage WebAssembly for better performance and modern API design.
Common errors
-
TypeError: xmllint.validateXML is not a function
cause The `xmllint` object was either not correctly imported/required, or the `validateXML` method is being called on an undefined variable.fixEnsure you are using `const xmllint = require('node-xmllint');` and then calling `xmllint.validateXML(...)`. Verify the module is installed correctly (`npm install node-xmllint`). -
ReferenceError: require is not defined
cause Attempting to use `require` in a browser environment or in a Node.js ESM module without proper bundling or transpilation.fixFor browser use, ensure you are bundling with a tool like Browserify (with `browserify-shim` as suggested in the README). For Node.js ESM, consider an ESM-compatible alternative or refactor to use CommonJS modules if feasible. -
Error: WebAssembly.instantiateStreaming(): Wasm code is not valid or exceeds the maximum size for synchronous compilation
cause This error typically occurs in browser environments due to Content-Security-Policy restrictions preventing WASM execution, or due to synchronous loading of large WASM binaries that exceed browser limits, or if the WASM file itself is corrupted or not served correctly.fixCheck your browser's Content-Security-Policy (CSP) headers; you might need to add `script-src 'unsafe-eval'` or `wasm-eval` directives. Ensure the WASM file is served with the correct MIME type (`application/wasm`). Consider using a library that employs asynchronous WASM loading (e.g., `xmllint-wasm`).
Warnings
- breaking The package `node-xmllint` is deprecated and has not been updated in approximately 8 years, making it effectively abandoned. It may contain unpatched security vulnerabilities or not be compatible with modern Node.js or browser environments. Consider using actively maintained forks like `xmllint-wasm` which provide WASM builds, updated libxml2 versions, and modern async APIs.
- gotcha The `validateXML` function is synchronous. For very large XML documents, this can block the Node.js event loop or freeze the browser UI, leading to poor user experience or server unresponsiveness. The underlying Emscripten port was not designed with asynchronous execution in mind for this API.
- gotcha The Emscripten-compiled `libxml2` library can result in a significant bundle size for browser applications (over 4MB for `xmllint.js`). This can negatively impact page load times, especially on slower networks.
- gotcha The package primarily exports a CommonJS module. Using it in modern Node.js ESM projects or with bundlers expecting ESM might require additional configuration (`"type": "module"` in package.json combined with `require()` is an anti-pattern and often problematic, or bundler-specific settings like `browserify-shim` mentioned in the README).
Install
-
npm install node-xmllint -
yarn add node-xmllint -
pnpm add node-xmllint
Imports
- xmllint
import xmllint from 'node-xmllint';
const xmllint = require('node-xmllint'); - validateXML
import { validateXML } from 'node-xmllint';const { validateXML } = require('node-xmllint'); // Direct destructuring, assuming it's an object property // Or, more accurately based on docs: const xmllint = require('node-xmllint'); xmllint.validateXML(...);
Quickstart
const xmllint = require('node-xmllint');
const xmlValid = `<root><item id="1"/></root>`;
const xmlInvalid = `<root><item></wrong></item></root>`;
const schemaValid = `<?xml version="1.0" encoding="UTF-8"?>\n<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">\n <xs:element name="root">\n <xs:complexType>\n <xs:sequence>\n <xs:element name="item" minOccurs="0" maxOccurs="unbounded">\n <xs:complexType>\n <xs:attribute name="id" type="xs:integer" use="optional"/>\n </xs:complexType>\n </xs:element>\n </xs:sequence>\n </xs:complexType>\n </xs:element>\n</xs:schema>`;
// Validate valid XML without schema
let result = xmllint.validateXML({ xml: xmlValid });
if (result.errors) {
console.error('Valid XML (no schema) validation errors:', result.errors);
} else {
console.log('Valid XML (no schema) is well-formed.');
}
// Validate invalid XML without schema
result = xmllint.validateXML({ xml: xmlInvalid });
if (result.errors) {
console.error('Invalid XML (no schema) validation errors:', result.errors);
} else {
console.log('Invalid XML (no schema) is well-formed.');
}
// Validate valid XML against a schema
result = xmllint.validateXML({ xml: xmlValid, schema: schemaValid });
if (result.errors) {
console.error('Valid XML (with schema) validation errors:', result.errors);
} else {
console.log('Valid XML (with schema) is valid.');
}
// Validate invalid XML against a schema (e.g., missing 'id' attribute if required)
const xmlSchemaInvalid = `<root><item/></root>`;
result = xmllint.validateXML({ xml: xmlSchemaInvalid, schema: schemaValid });
if (result.errors) {
console.error('Invalid XML (with schema) validation errors:', result.errors);
} else {
console.log('Invalid XML (with schema) is valid.');
}