Simple XML to JavaScript object converter.
Default configuration presets and validation error handling for different API versions and usage patterns.
The defaults module provides version-specific configuration presets that match different API behaviors and compatibility levels.
const defaults: {
"0.1": DefaultOptions;
"0.2": DefaultOptions;
};
interface DefaultOptions {
explicitArray: boolean;
ignoreAttrs: boolean;
mergeAttrs: boolean;
normalize: boolean;
normalizeTags: boolean;
attrkey: string;
charkey: string;
explicitCharkey: boolean;
trim: boolean;
explicitRoot: boolean;
emptyTag: string;
strict: boolean;
}Usage Examples:
const xml2js = require('xml2js');
// Access default configurations
console.log(xml2js.defaults['0.1']);
console.log(xml2js.defaults['0.2']);
// Use version-specific defaults
const parser01 = new xml2js.Parser(xml2js.defaults['0.1']);
const parser02 = new xml2js.Parser(xml2js.defaults['0.2']);
// Extend defaults with custom options
const customOptions = Object.assign({}, xml2js.defaults['0.2'], {
trim: true,
parseNumbers: true,
tagNameProcessors: [xml2js.processors.firstCharLowerCase]
});
const customParser = new xml2js.Parser(customOptions);Legacy configuration preset for backwards compatibility with older xml2js behavior.
const version01Defaults: {
explicitArray: false;
ignoreAttrs: false;
mergeAttrs: false;
normalize: true;
normalizeTags: false;
attrkey: "@";
charkey: "#";
explicitCharkey: false;
trim: true;
explicitRoot: false;
emptyTag: "";
strict: true;
validator: null;
xmlns: false;
explicitChildren: false;
childkey: "@@";
charsAsChildren: false;
includeWhiteChars: false;
async: false;
attrNameProcessors: null;
attrValueProcessors: null;
tagNameProcessors: null;
valueProcessors: null;
};Characteristics of Version 0.1:
explicitArray: false - Single child elements are not wrapped in arraysignoreAttrs: false - XML attributes are preservednormalize: true and trim: true - Text processing enabled by defaultexplicitRoot: false - Root element not wrapped in result@ for attributes, # for character contentUsage Examples:
const xml2js = require('xml2js');
// Parser with 0.1 defaults
const legacyParser = new xml2js.Parser(xml2js.defaults['0.1']);
const xmlString = '<person name="John"><age>30</age></person>';
legacyParser.parseString(xmlString, (err, result) => {
if (!err) {
console.log(result);
// With 0.1 defaults: { person: { '@': { name: 'John' }, age: '30' } }
// Note: attributes preserved with @ key, no root wrapper
}
});Current default configuration providing more comprehensive XML handling with attribute support.
const version02Defaults: {
explicitArray: true;
ignoreAttrs: false;
mergeAttrs: false;
normalize: false;
normalizeTags: false;
attrkey: "$";
charkey: "_";
explicitCharkey: false;
trim: false;
explicitRoot: true;
emptyTag: "";
strict: true;
validator: null;
xmlns: false;
explicitChildren: false;
preserveChildrenOrder: false;
childkey: "$$";
charsAsChildren: false;
includeWhiteChars: false;
async: false;
attrNameProcessors: null;
attrValueProcessors: null;
tagNameProcessors: null;
valueProcessors: null;
rootName: "root";
xmldec: {
version: "1.0";
encoding: "UTF-8";
standalone: true;
};
doctype: null;
renderOpts: {
pretty: true;
indent: " ";
newline: "\n";
};
headless: false;
chunkSize: 10000;
cdata: false;
};Characteristics of Version 0.2:
explicitArray: true - All child elements are wrapped in arrays for consistencyignoreAttrs: false - XML attributes are preserved and accessibleUsage Examples:
const xml2js = require('xml2js');
// Parser with 0.2 defaults (current default)
const modernParser = new xml2js.Parser(xml2js.defaults['0.2']);
const xmlString = '<person name="John"><age>30</age></person>';
modernParser.parseString(xmlString, (err, result) => {
if (!err) {
console.log(result);
// With 0.2 defaults: { person: { $: { name: 'John' }, age: ['30'] } }
// Note: attributes preserved, age is an array
}
});const xml2js = require('xml2js');
// Web API friendly configuration
const webApiConfig = Object.assign({}, xml2js.defaults['0.2'], {
explicitArray: false, // Simpler structure
mergeAttrs: true, // Merge attributes with content
trim: true, // Clean whitespace
tagNameProcessors: [xml2js.processors.firstCharLowerCase],
valueProcessors: [xml2js.processors.parseNumbers, xml2js.processors.parseBooleans]
});
// Configuration for processing RSS/Atom feeds
const feedConfig = Object.assign({}, xml2js.defaults['0.2'], {
explicitArray: false,
trim: true,
normalize: true,
tagNameProcessors: [xml2js.processors.normalize],
valueProcessors: [xml2js.processors.parseNumbers]
});
// Configuration for SOAP/XML services
const soapConfig = Object.assign({}, xml2js.defaults['0.2'], {
explicitArray: false,
tagNameProcessors: [xml2js.processors.stripPrefix],
xmlns: true, // Preserve namespace information
explicitRoot: false
});Custom error class for XML validation and parsing failures, extending the standard JavaScript Error class.
/**
* Custom error class for XML validation failures
*/
class ValidationError extends Error {
/**
* Create a ValidationError
* @param message - Error message describing the validation failure
*/
constructor(message: string);
}Usage Examples:
const xml2js = require('xml2js');
// ValidationError is thrown for validation failures
const parser = new xml2js.Parser({
validator: (xpath, currentValue, newValue) => {
// Custom validation logic
if (xpath === '/product/price' && isNaN(parseFloat(newValue))) {
throw new xml2js.ValidationError(`Invalid price value: ${newValue}`);
}
return newValue;
}
});
const invalidXml = '<product><price>not-a-number</price></product>';
parser.parseString(invalidXml, (err, result) => {
if (err instanceof xml2js.ValidationError) {
console.error('Validation failed:', err.message);
// Handle validation error specifically
} else if (err) {
console.error('Parse error:', err.message);
// Handle other parsing errors
} else {
console.log('Parse successful:', result);
}
});
// Using with promises
async function parseWithValidation(xmlString) {
try {
const result = await parser.parseStringPromise(xmlString);
return result;
} catch (error) {
if (error instanceof xml2js.ValidationError) {
console.error('Validation error:', error.message);
throw new Error(`XML validation failed: ${error.message}`);
}
throw error;
}
}const xml2js = require('xml2js');
// Complex validation example
function createValidatingParser(schema) {
return new xml2js.Parser({
validator: (xpath, currentValue, newValue) => {
const rule = schema[xpath];
if (rule) {
// Type validation
if (rule.type === 'number' && isNaN(parseFloat(newValue))) {
throw new xml2js.ValidationError(`Expected number at ${xpath}, got: ${newValue}`);
}
// Range validation
if (rule.type === 'number' && rule.min !== undefined) {
const numValue = parseFloat(newValue);
if (numValue < rule.min) {
throw new xml2js.ValidationError(`Value ${numValue} at ${xpath} is below minimum ${rule.min}`);
}
}
// String length validation
if (rule.type === 'string' && rule.maxLength !== undefined) {
if (newValue.length > rule.maxLength) {
throw new xml2js.ValidationError(`String at ${xpath} exceeds maximum length ${rule.maxLength}`);
}
}
// Required field validation
if (rule.required && (!newValue || newValue.trim() === '')) {
throw new xml2js.ValidationError(`Required field ${xpath} is empty`);
}
}
return newValue;
}
});
}
// Define validation schema
const productSchema = {
'/product/id': { type: 'number', required: true, min: 1 },
'/product/name': { type: 'string', required: true, maxLength: 100 },
'/product/price': { type: 'number', required: true, min: 0 },
'/product/description': { type: 'string', maxLength: 500 }
};
const validatingParser = createValidatingParser(productSchema);
// Test with valid XML
const validXml = `
<product>
<id>123</id>
<name>Laptop</name>
<price>999.99</price>
<description>High-performance laptop</description>
</product>
`;
// Test with invalid XML
const invalidXml = `
<product>
<id>0</id>
<name></name>
<price>-100</price>
<description>${'x'.repeat(600)}</description>
</product>
`;
validatingParser.parseString(validXml, (err, result) => {
if (err instanceof xml2js.ValidationError) {
console.error('Validation failed:', err.message);
} else if (!err) {
console.log('Valid XML parsed successfully');
}
});const xml2js = require('xml2js');
// For simple XML consumption (e.g., configuration files)
const simpleConfig = xml2js.defaults['0.1']; // No arrays, ignores attributes
// For comprehensive XML processing (e.g., APIs, complex documents)
const comprehensiveConfig = xml2js.defaults['0.2']; // Preserves structure
// For web applications (JSON-like structure)
const webConfig = Object.assign({}, xml2js.defaults['0.2'], {
explicitArray: false,
mergeAttrs: true
});const xml2js = require('xml2js');
// High-performance parsing for large documents
const performanceConfig = {
// Minimal processing
explicitArray: false,
ignoreAttrs: true,
trim: false,
normalize: false,
// No text processors to avoid overhead
tagNameProcessors: null,
valueProcessors: null,
// Async processing for large documents
async: true,
chunkSize: 50000
};
// Memory-efficient parsing
const memoryEfficientConfig = {
explicitArray: false,
explicitRoot: false,
trim: true,
emptyTag: null, // Don't create empty values
strict: false // More lenient parsing
};const xml2js = require('xml2js');
// Comprehensive error handling
function createRobustParser(options = {}) {
const defaultOptions = Object.assign({}, xml2js.defaults['0.2'], {
// Enable strict validation
strict: true,
// Custom validator for business logic
validator: (xpath, currentValue, newValue) => {
try {
// Apply custom validation rules here
return newValue;
} catch (validationError) {
throw new xml2js.ValidationError(`Validation failed at ${xpath}: ${validationError.message}`);
}
}
}, options);
return new xml2js.Parser(defaultOptions);
}
// Usage with comprehensive error handling
async function safeParseXML(xmlString, options) {
const parser = createRobustParser(options);
try {
const result = await parser.parseStringPromise(xmlString);
return { success: true, data: result };
} catch (error) {
if (error instanceof xml2js.ValidationError) {
return {
success: false,
error: 'validation',
message: error.message
};
} else {
return {
success: false,
error: 'parsing',
message: error.message
};
}
}
}Install with Tessl CLI
npx tessl i tessl/npm-xml2js