xml-xsd-engine
v1.2.6
Published
Zero-dependency XML parser, XSD parser, schema model and validation engine written in TypeScript
Downloads
672
Maintainers
Readme
xml-xsd-engine
Fast, zero-dependency XML + XSD validation engine for Node.js and browsers — written in TypeScript from scratch.
✔ XML parser (DOM + SAX + Streaming) ✔ XSD schema validation
✔ XPath query engine ✔ XML ↔ JSON transforms
✔ XSLT-lite transformations ✔ Schema cache + Batch validation
✔ CLI xml-validate file.xml schema.xsd ✔ Secure by default (XXE-safe)Quick Start
npm install xml-xsd-engineimport { parseXml, parseXsd, validate } from 'xml-xsd-engine';
const xml = `<book><title>Dune</title></book>`;
const xsd = `
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="book">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>`;
const result = validate(parseXml(xml), parseXsd(xsd));
console.log(result.valid); // trueWhy this library?
Most JavaScript XML libraries only parse XML. xml-xsd-engine is a complete XML processing stack in a single zero-dependency package:
| Feature | xml-xsd-engine | fast-xml-parser | xml2js | xmldom | |---|:---:|:---:|:---:|:---:| | XML parsing (DOM) | ✅ | ✅ | ✅ | ✅ | | SAX / event streaming | ✅ | ✅ | ✅ | ✅ | | XPath queries | ✅ | ❌ | ❌ | ✅ | | XSD schema validation | ✅ | ❌ | ❌ | ❌ | | XML ↔ JSON transforms | ✅ | ✅ | ✅ | ❌ | | XSLT transformations | ✅ | ❌ | ❌ | ❌ | | Schema cache | ✅ | ❌ | ❌ | ❌ | | Batch validation | ✅ | ❌ | ❌ | ❌ | | TypeScript-first | ✅ | ✅ | ⚠️ | ⚠️ | | Zero runtime deps | ✅ | ✅ | ❌ | ❌ | | XXE safe by default | ✅ | ⚠️ | ⚠️ | ⚠️ |
Installation
npm install xml-xsd-engine
# or
yarn add xml-xsd-engine
pnpm add xml-xsd-engineRequirements: Node.js ≥ 18 · ESM or CommonJS · Zero runtime dependencies
Core Features
Parse XML
import { parseXml } from 'xml-xsd-engine';
const doc = parseXml('<catalog><book id="1"><title>Dune</title></book></catalog>');
doc.root?.getAttribute('id'); // null (on catalog)
doc.root?.find('book/title')?.textContent; // "Dune"Validate against XSD
import { parseXml, parseXsd, validate } from 'xml-xsd-engine';
const result = validate(parseXml(xml), parseXsd(xsd));
console.log(result.valid); // true | false
result.errors.forEach(e => console.error(`${e.path}: ${e.message}`));XPath Queries
import { xpath } from 'xml-xsd-engine';
const books = xpath(doc, '//book[@lang="en"]');
const title = xpath.string(doc, '//title');
const count = xpath.count(doc, '//book');SAX Parser (O(depth) memory)
import { parseSax } from 'xml-xsd-engine';
parseSax(xml, {
startElement: e => console.log('open', e.localName),
endElement: e => console.log('close', e.localName),
text: e => console.log('text', e.value),
});XML ↔ JSON
import { xmlToJson, jsonToXmlString } from 'xml-xsd-engine';
const obj = xmlToJson(doc, { coerceNumbers: true });
// { catalog: { book: [{ "@id": 1, title: "Dune" }] } }
const xml = jsonToXmlString({ book: { '@id': '1', title: 'Dune' } });
// <book id="1"><title>Dune</title></book>XSLT Transformation
import { transformXml, XsltTransformer } from 'xml-xsd-engine';
const result = transformXml(sourceXml, stylesheetXml);
const t = new XsltTransformer(stylesheetXml); // compile once
const out1 = t.transform(xml1); // reuse many timesSchema Cache (server use)
import { globalSchemaCache } from 'xml-xsd-engine';
// Schema compiled once, cached forever (LRU + TTL)
const result = await globalSchemaCache.validateFile('req.xml', 'schema.xsd');Batch Validation
import { batchValidateFiles } from 'xml-xsd-engine';
const report = await batchValidateFiles(['a.xml', 'b.xml', 'c.xml'], 'schema.xsd', {
concurrency: 8,
onProgress: (file, r) => console.log(file, r.valid ? '✔' : '✘'),
});
console.log(report.summary); // "3 passed, 0 failed in 22ms"Streaming (GB-scale files)
import { parseXmlFileStream } from 'xml-xsd-engine';
const doc = await parseXmlFileStream('./large.xml'); // chunked, low memoryCLI
# Validate a file
xml-validate document.xml schema.xsd
# Multiple files
xml-validate data/*.xml schema.xsd --format compact
# Well-formedness only (no schema)
xml-validate --well-formed document.xml
# GitHub Actions annotations
xml-validate document.xml schema.xsd --format github
# JUnit output for CI systems
xml-validate document.xml schema.xsd --format junit --output results.xml
# Quiet mode — exit code only
xml-validate document.xml schema.xsd --quiet && echo "OK"Exit codes: 0 valid · 1 validation errors · 2 usage/file error
Architecture
XML Input
│
┌─────▼─────┐
│ XmlLexer │ single-pass state machine, no regex
└─────┬─────┘
│ token stream
┌────────▼────────┐
│ XmlParser / SAX │ stack-based, namespace-aware
└────────┬────────┘
│
DOM Tree
│
┌──────────┼──────────┐
│ │ │
XPath Serializer Transform
│ │
Query JSON / XSLT
│
┌─────────▼─────────┐
│ XSD Parser │
│ Schema Model │ compiled once
│ Validation Engine │
└─────────┬─────────┘
│
┌──────▼──────┐
│ CLI / Batch │
└─────────────┘Security
Built-in protections — all on by default, not configurable off:
| Threat | Protection |
|---|---|
| XXE injection | SYSTEM/PUBLIC entity URIs never fetched |
| Billion Laughs | Entity expansion capped at 1 000 000 chars |
| Deep nesting DoS | maxDepth limit (default 500) |
| Attribute flood | maxAttributes limit (default 256) |
| Giant text node | maxTextLength limit (default 10 000 000) |
| Node count bomb | maxNodeCount limit (default 1 000 000) |
import { ParseBudget } from 'xml-xsd-engine';
// Extra limits for untrusted input
const doc = new ParseBudget({ wallTimeMs: 2_000, bytes: 512_000 }).parse(untrusted);Documentation
| | |
|---|---|
| Quick Start | 10 common recipes in 5 minutes |
| Usage Guide | Full recipes for every feature |
| API Reference | Every export, option, and type |
| Architecture | Internal design + data flow |
| Error Codes | All 36 XmlErrorCode values |
| Migration Guide | Upgrading between versions |
| Testing Guide | How tests are structured |
| Publishing Guide | Build + ESM/CJS architecture |
| Security Policy | Threat model + secure checklist |
| Roadmap | Upcoming features + versions |
| Changelog | Version history |
Examples
Runnable TypeScript examples in examples/:
| Example | What it shows |
|---|---|
| 01-basic-parse | DOM navigation, XPath, serialization |
| 02-xsd-validation | Schema validation, error handling |
| 03-streaming-parser | SAX push/pull API, file streaming |
| 04-xml-to-json | xmlToJson, jsonToXml, round-trip |
| 05-xslt-transform | transformXml, sort, filter, AVTs |
| 06-cli-validation | CLI + programmatic file validation |
# Run any example
npx ts-node examples/01-basic-parse/index.tsRoadmap
| Version | Focus | |---|---| | v1.3 | XPath improvements, source-mapped error locations | | v1.4 | Streaming XSD validation, async schema loaders | | v1.5 | XML diff utility, schema inference from XML | | v2.0 | Streaming-first architecture, XSD 1.1, Schematron |
Contributing
Contributions are welcome!
All PRs run through CI (build + 429 tests + ESLint + TypeScript strict check).
Current coverage: stmts 70% · branches 60% · functions 70% · lines 75%
Run npm run test:coverage to see the full per-file breakdown.
License
MIT © 2024–2026 xml-xsd-engine contributors
