A pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and XMLSerializer module
Comprehensive error reporting system with DOM-standard exceptions and parsing-specific error types for robust XML processing applications.
Standard DOM exception class for DOM manipulation errors.
/**
* DOM-specific exception class following W3C standards
* Thrown by DOM operations that encounter exceptional conditions
*/
class DOMException extends Error {
constructor(message?: string, name?: string);
constructor(code?: number, message?: string);
readonly name: string; // Exception name
readonly code: number; // Numeric exception code (0 for modern names)
// Static exception codes (legacy)
static readonly INDEX_SIZE_ERR: 1;
static readonly DOMSTRING_SIZE_ERR: 2;
static readonly HIERARCHY_REQUEST_ERR: 3;
static readonly WRONG_DOCUMENT_ERR: 4;
static readonly INVALID_CHARACTER_ERR: 5;
static readonly NO_DATA_ALLOWED_ERR: 6;
static readonly NO_MODIFICATION_ALLOWED_ERR: 7;
static readonly NOT_FOUND_ERR: 8;
static readonly NOT_SUPPORTED_ERR: 9;
static readonly INUSE_ATTRIBUTE_ERR: 10;
static readonly INVALID_STATE_ERR: 11;
static readonly SYNTAX_ERR: 12;
static readonly INVALID_MODIFICATION_ERR: 13;
static readonly NAMESPACE_ERR: 14;
static readonly INVALID_ACCESS_ERR: 15;
static readonly VALIDATION_ERR: 16;
static readonly TYPE_MISMATCH_ERR: 17;
static readonly SECURITY_ERR: 18;
static readonly NETWORK_ERR: 19;
static readonly ABORT_ERR: 20;
static readonly URL_MISMATCH_ERR: 21;
static readonly QUOTA_EXCEEDED_ERR: 22;
static readonly TIMEOUT_ERR: 23;
static readonly INVALID_NODE_TYPE_ERR: 24;
static readonly DATA_CLONE_ERR: 25;
}Usage Examples:
const { DOMParser, DOMException } = require('@xmldom/xmldom');
try {
const doc = parser.parseFromString('<root></root>', 'text/xml');
const root = doc.documentElement;
// This might throw a DOMException
root.removeChild(doc.createElement('nonexistent'));
} catch (error) {
if (error instanceof DOMException) {
console.log(`DOM Error: ${error.name} (${error.code}): ${error.message}`);
switch (error.name) {
case 'NotFoundError':
console.log('Attempted to remove non-existent child');
break;
case 'HierarchyRequestError':
console.log('Invalid tree modification');
break;
case 'WrongDocumentError':
console.log('Node belongs to different document');
break;
}
}
}Specialized error class for XML parsing failures.
/**
* Error thrown during XML parsing when fatal errors occur
* Provides additional context about parse location and cause
*/
class ParseError extends Error {
constructor(message: string, locator?: any, cause?: Error);
readonly message: string;
readonly locator?: any; // Location information if available
readonly cause?: Error; // Underlying cause if chained
}Usage Examples:
const { DOMParser, ParseError } = require('@xmldom/xmldom');
const parser = new DOMParser({
onError: (level, message, context) => {
if (level === 'fatalError') {
throw new ParseError(`Fatal parsing error: ${message}`, context);
}
}
});
try {
const doc = parser.parseFromString('<invalid><xml>', 'text/xml');
} catch (error) {
if (error instanceof ParseError) {
console.log(`Parse Error: ${error.message}`);
if (error.locator) {
console.log(`Location: line ${error.locator.lineNumber}, column ${error.locator.columnNumber}`);
}
}
}/**
* Standard DOM exception names
*/
const DOMExceptionName = {
Error: 'Error',
IndexSizeError: 'IndexSizeError', // deprecated
DomstringSizeError: 'DomstringSizeError', // deprecated
HierarchyRequestError: 'HierarchyRequestError',
WrongDocumentError: 'WrongDocumentError',
InvalidCharacterError: 'InvalidCharacterError',
NoDataAllowedError: 'NoDataAllowedError', // deprecated
NoModificationAllowedError: 'NoModificationAllowedError',
NotFoundError: 'NotFoundError',
NotSupportedError: 'NotSupportedError',
InUseAttributeError: 'InUseAttributeError',
InvalidStateError: 'InvalidStateError',
SyntaxError: 'SyntaxError',
InvalidModificationError: 'InvalidModificationError',
NamespaceError: 'NamespaceError',
InvalidAccessError: 'InvalidAccessError', // deprecated
ValidationError: 'ValidationError', // deprecated
TypeMismatchError: 'TypeMismatchError', // deprecated
SecurityError: 'SecurityError',
NetworkError: 'NetworkError',
AbortError: 'AbortError',
URLMismatchError: 'URLMismatchError', // deprecated
QuotaExceededError: 'QuotaExceededError',
TimeoutError: 'TimeoutError',
InvalidNodeTypeError: 'InvalidNodeTypeError',
DataCloneError: 'DataCloneError',
EncodingError: 'EncodingError',
NotReadableError: 'NotReadableError',
UnknownError: 'UnknownError',
ConstraintError: 'ConstraintError',
DataError: 'DataError',
TransactionInactiveError: 'TransactionInactiveError',
ReadOnlyError: 'ReadOnlyError',
VersionError: 'VersionError',
OperationError: 'OperationError',
NotAllowedError: 'NotAllowedError',
OptOutError: 'OptOutError'
};
/**
* Legacy numeric exception codes
*/
const ExceptionCode = {
INDEX_SIZE_ERR: 1,
DOMSTRING_SIZE_ERR: 2,
HIERARCHY_REQUEST_ERR: 3,
WRONG_DOCUMENT_ERR: 4,
INVALID_CHARACTER_ERR: 5,
NO_DATA_ALLOWED_ERR: 6,
NO_MODIFICATION_ALLOWED_ERR: 7,
NOT_FOUND_ERR: 8,
NOT_SUPPORTED_ERR: 9,
INUSE_ATTRIBUTE_ERR: 10,
INVALID_STATE_ERR: 11,
SYNTAX_ERR: 12,
INVALID_MODIFICATION_ERR: 13,
NAMESPACE_ERR: 14,
INVALID_ACCESS_ERR: 15,
VALIDATION_ERR: 16,
TYPE_MISMATCH_ERR: 17,
SECURITY_ERR: 18,
NETWORK_ERR: 19,
ABORT_ERR: 20,
URL_MISMATCH_ERR: 21,
QUOTA_EXCEEDED_ERR: 22,
TIMEOUT_ERR: 23,
INVALID_NODE_TYPE_ERR: 24,
DATA_CLONE_ERR: 25
};DOM Manipulation Errors:
const { DOMParser, DOMException } = require('@xmldom/xmldom');
const parser = new DOMParser();
const doc1 = parser.parseFromString('<root1></root1>', 'text/xml');
const doc2 = parser.parseFromString('<root2></root2>', 'text/xml');
try {
// WrongDocumentError: Cannot adopt node from different document
doc1.documentElement.appendChild(doc2.documentElement);
} catch (error) {
console.log(error.name); // 'WrongDocumentError'
}
try {
// HierarchyRequestError: Cannot insert node as child of itself
const root = doc1.documentElement;
root.appendChild(root);
} catch (error) {
console.log(error.name); // 'HierarchyRequestError'
}
try {
// NotFoundError: Attribute doesn't exist
const attr = doc1.documentElement.getAttributeNode('nonexistent');
doc1.documentElement.removeAttributeNode(attr);
} catch (error) {
console.log(error.name); // 'NotFoundError'
}Parsing Error Handling:
const { DOMParser, ParseError, onErrorStopParsing } = require('@xmldom/xmldom');
// Custom error handler
const parser = new DOMParser({
onError: (level, message, context) => {
const location = context ? `at line ${context.lineNumber}, column ${context.columnNumber}` : '';
console.log(`${level.toUpperCase()}: ${message} ${location}`);
if (level === 'fatalError') {
throw new ParseError(message, context);
}
}
});
// Using predefined error handlers
const strictParser = new DOMParser({
onError: onErrorStopParsing // Stops on any error
});
const veryStrictParser = new DOMParser({
onError: onWarningStopParsing // Stops on warnings too
});Error Recovery Strategies:
function parseXmlSafely(xmlString, fallbackValue = null) {
const parser = new DOMParser({
onError: (level, message) => {
console.warn(`XML ${level}: ${message}`);
// Log but continue parsing for warnings and errors
// Only fatal errors will throw
}
});
try {
return parser.parseFromString(xmlString, 'text/xml');
} catch (error) {
if (error instanceof ParseError) {
console.error('Failed to parse XML:', error.message);
return fallbackValue;
}
throw error; // Re-throw unexpected errors
}
}
// Usage
const doc = parseXmlSafely('<invalid><xml>', null);
if (doc === null) {
console.log('Parsing failed, using fallback');
}Validation and Error Prevention:
const { isValidMimeType, MIME_TYPE } = require('@xmldom/xmldom');
function safeParseFromString(xmlString, mimeType) {
// Validate MIME type before parsing
if (!isValidMimeType(mimeType)) {
throw new TypeError(`Invalid MIME type: ${mimeType}`);
}
// Validate input
if (typeof xmlString !== 'string') {
throw new TypeError('XML source must be a string');
}
if (xmlString.trim() === '') {
throw new Error('XML source cannot be empty');
}
const parser = new DOMParser();
return parser.parseFromString(xmlString, mimeType);
}
// Safe usage
try {
const doc = safeParseFromString('<root></root>', MIME_TYPE.XML_APPLICATION);
} catch (error) {
console.error('Safe parsing failed:', error.message);
}const { DOMParser } = require('@xmldom/xmldom');
// Comprehensive error logging
const debugParser = new DOMParser({
locator: true, // Enable location tracking
onError: (level, message, context) => {
const timestamp = new Date().toISOString();
const location = context && context.lineNumber ?
`${context.lineNumber}:${context.columnNumber}` : 'unknown';
const logEntry = {
timestamp,
level,
message,
location,
context: context ? { ...context } : null
};
console.log('XML Parse Event:', JSON.stringify(logEntry, null, 2));
// Store in application log
if (typeof applicationLogger !== 'undefined') {
applicationLogger.log(level, 'XML Parse Error', logEntry);
}
}
});Install with Tessl CLI
npx tessl i tessl/npm-xmldom--xmldom