@compare-xml/core (JavaScript)
Parse and deeply compare XML strings with the same engine used by the website.
@compare-xml/core is a lightweight JavaScript/TypeScript library for deep comparison of XML documents—the same engine that powers Compare XML. It parses XML with fast-xml-parser and detects additions, deletions, and value changes between two XML structures.
Language: JavaScript/TypeScript — distributed via npm.
Installation
# npm
npm install @compare-xml/core
# yarn
yarn add @compare-xml/core
# pnpm
pnpm add @compare-xml/core
Quick Start
import { compareXML } from '@compare-xml/core';
const baseXML = '<user><name>Alice</name><age>30</age><hobbies><item>reading</item></hobbies></user>';
const contrastXML = '<user><name>Bob</name><age>30</age><hobbies><item>reading</item><item>coding</item></hobbies><email>[email protected]</email></user>';
const differences = compareXML({ baseXML, contrastXML });
console.log(differences);
// [
// { pathSegments: ['user', 'name'], pathString: 'user.name', pathBelongsTo: 'both', diffType: 'valueChanged' },
// { pathSegments: ['user', 'hobbies', 'item'], pathString: 'user.hobbies.item', pathBelongsTo: 'both', diffType: 'valueChanged' },
// { pathSegments: ['user', 'email'], pathString: 'user.email', pathBelongsTo: 'contrast', diffType: 'added' },
// ]
The default byIndex method compares the single Base item with the repeated Contrast item collection as values at that path. Use repeated elements on both sides when you want index-by-index collection alignment.
Compare Options
import { compareXML } from '@compare-xml/core';
// Case-insensitive element and attribute names
compareXML({
baseXML: '<root><Name>Alice</Name></root>',
contrastXML: '<root><name>Alice</name></root>',
options: { keyCaseInsensitive: true },
});
// [] (no differences)
// Case-insensitive text and attribute values
compareXML({
baseXML: '<root><status>OK</status></root>',
contrastXML: '<root><status>ok</status></root>',
options: { valueCaseInsensitive: true },
});
// [] (no differences)
The parser automatically converts numeric-looking element text and attribute values to numbers. There is no separate numeric-string option in XMLCompareOptions.
Repeated-Element Comparison Methods
Repeated child elements, such as multiple <item> nodes, are compared as arrays:
import { compareXML } from '@compare-xml/core';
// 'byIndex' (default) — compares elements at the same index
compareXML({
baseXML: '<root><items><item>1</item><item>2</item><item>3</item></items></root>',
contrastXML: '<root><items><item>2</item><item>3</item><item>4</item></items></root>',
});
// 'lcs' — uses Longest Common Subsequence for ordered alignment
compareXML({
baseXML: '<root><items><item>1</item><item>2</item><item>3</item></items></root>',
contrastXML: '<root><items><item>2</item><item>3</item><item>4</item></items></root>',
options: { arrayCompareMethod: 'lcs' },
});
// 'unordered' — treats repeated elements as a multiset
compareXML({
baseXML: '<root><items><item>1</item><item>2</item><item>3</item></items></root>',
contrastXML: '<root><items><item>3</item><item>2</item><item>1</item></items></root>',
options: { arrayCompareMethod: 'unordered' },
});
// [] (no differences)
Unordered matching ignores position but not duplicate occurrence counts. See XML Comparison Rules for examples and guidance on choosing a method.
Formatting Paths
import { pathSegmentsToString } from '@compare-xml/core';
pathSegmentsToString(['users', '[0]', 'name']);
// 'users[0].name'
API Reference
compareXML
function compareXML(params: {
baseXML: string;
contrastXML: string;
options?: XMLCompareOptions;
}): XMLValueDifference[];
Parses two XML strings and deeply compares their structures. It returns an empty array when the documents are equal and throws XMLValidationError when either input is not well-formed XML.
| Parameter | Type | Description |
|---|---|---|
baseXML | string | The base XML string, considered the original side. |
contrastXML | string | The XML string compared against the base. |
options | XMLCompareOptions | Optional comparison behavior. |
parseXML
function parseXML(xml: string): unknown;
Parses an XML string into a JavaScript value using fast-xml-parser. Attribute names are prefixed with @.
validateXML
function validateXML(xml: string): void;
Validates that a string is well-formed XML. It throws XMLValidationError for empty, whitespace-only, or malformed input. The error includes line and col properties when position information is available.
pathSegmentsToString
function pathSegmentsToString(pathSegments: string[]): string;
Converts path segments from XMLValueDifference.pathSegments into a human-readable string. Array index segments are appended without a leading dot; other segments are joined with ..
pathSegmentsToString([]); // ''
pathSegmentsToString(['user', 'name']); // 'user.name'
pathSegmentsToString(['items', '[2]', 'id']); // 'items[2].id'
XMLCompareOptions
| Option | Type | Default | Description |
|---|---|---|---|
arrayCompareMethod | XMLArrayCompareMethod | 'byIndex' | Strategy used to compare repeated elements. |
keyCaseInsensitive | boolean | false | Compare element and attribute names case-insensitively. |
valueCaseInsensitive | boolean | false | Compare text and attribute values case-insensitively. |
XMLArrayCompareMethod
type XMLArrayCompareMethod = 'byIndex' | 'lcs' | 'unordered';
| Value | Description |
|---|---|
'byIndex' | Compare elements pairwise at the same index; extra trailing elements are added or deleted. |
'lcs' | Use Longest Common Subsequence to align ordered collections. |
'unordered' | Match equal elements regardless of position as a multiset, including duplicate counts. |
XMLValueDiffType
type XMLValueDiffType = 'added' | 'deleted' | 'valueChanged';
| Value | Description |
|---|---|
'added' | An element or attribute exists in contrastXML but not in baseXML. |
'deleted' | An element or attribute exists in baseXML but not in contrastXML. |
'valueChanged' | The value changed between Base and Contrast. |
XMLValueDifference
| Field | Type | Description |
|---|---|---|
pathSegments | string[] | Path segments; array indices appear as '[n]'. |
pathString | string | Dot-notation path with array indices kept as bracket suffixes. |
pathBelongsTo | 'base' | 'contrast' | 'both' | Side that owns the path. |
diffType | XMLValueDiffType | Kind of difference detected at this path. |
XMLValidationError
class XMLValidationError extends Error {
line?: number;
col?: number;
}
Thrown by validateXML and compareXML when XML validation fails. line and col are available when the parser supplies position information.
License
MIT