0
# Error Handling
1
2
Robust error handling system with DOMException classes, configurable parsing error handlers, detailed error reporting, and comprehensive error code support following W3C DOM specifications.
3
4
## Capabilities
5
6
### DOMException Class
7
8
The DOMException class represents errors that occur during DOM operations, providing specific error codes and descriptive messages.
9
10
```javascript { .api }
11
/**
12
* W3C DOMException class for DOM operation errors
13
*/
14
class DOMException extends Error {
15
/**
16
* Creates a new DOMException
17
* @param code The error code constant
18
* @param message Optional additional error message
19
*/
20
constructor(code: number, message?: string);
21
22
/**
23
* The error code indicating the type of error
24
*/
25
readonly code: number;
26
27
/**
28
* Error message describing the exception
29
*/
30
readonly message: string;
31
32
// Error code constants
33
static readonly INDEX_SIZE_ERR: 1;
34
static readonly DOMSTRING_SIZE_ERR: 2;
35
static readonly HIERARCHY_REQUEST_ERR: 3;
36
static readonly WRONG_DOCUMENT_ERR: 4;
37
static readonly INVALID_CHARACTER_ERR: 5;
38
static readonly NO_DATA_ALLOWED_ERR: 6;
39
static readonly NO_MODIFICATION_ALLOWED_ERR: 7;
40
static readonly NOT_FOUND_ERR: 8;
41
static readonly NOT_SUPPORTED_ERR: 9;
42
static readonly INUSE_ATTRIBUTE_ERR: 10;
43
static readonly INVALID_STATE_ERR: 11;
44
static readonly SYNTAX_ERR: 12;
45
static readonly INVALID_MODIFICATION_ERR: 13;
46
static readonly NAMESPACE_ERR: 14;
47
static readonly INVALID_ACCESS_ERR: 15;
48
}
49
```
50
51
**Usage Examples:**
52
53
```javascript
54
const { DOMParser, DOMException } = require('xmldom');
55
const parser = new DOMParser();
56
const doc = parser.parseFromString('<root></root>', 'text/xml');
57
58
try {
59
// Attempt invalid DOM operation
60
const element = doc.createElement('test');
61
const otherDoc = parser.parseFromString('<other></other>', 'text/xml');
62
63
// This will throw WRONG_DOCUMENT_ERR
64
element.appendChild(otherDoc.documentElement);
65
} catch (error) {
66
if (error instanceof DOMException) {
67
console.log(`DOM Error Code: ${error.code}`);
68
console.log(`Error Type: ${error.name}`);
69
console.log(`Message: ${error.message}`);
70
71
switch (error.code) {
72
case DOMException.WRONG_DOCUMENT_ERR:
73
console.log('Attempted to use node from different document');
74
break;
75
case DOMException.HIERARCHY_REQUEST_ERR:
76
console.log('Invalid node hierarchy operation');
77
break;
78
case DOMException.INVALID_CHARACTER_ERR:
79
console.log('Invalid character in name');
80
break;
81
default:
82
console.log('Other DOM exception');
83
}
84
}
85
}
86
87
// Examples of operations that throw specific exceptions
88
try {
89
doc.createElement('invalid name with spaces'); // INVALID_CHARACTER_ERR
90
} catch (e) {
91
console.log(`Invalid character error: ${e.code}`);
92
}
93
94
try {
95
const element = doc.createElement('test');
96
element.removeChild(doc.createElement('notAChild')); // NOT_FOUND_ERR
97
} catch (e) {
98
console.log(`Not found error: ${e.code}`);
99
}
100
```
101
102
### Parse Error Handling
103
104
Configurable error handling during XML parsing with support for warnings, errors, and fatal errors.
105
106
```javascript { .api }
107
/**
108
* Error handler configuration for DOMParser
109
*/
110
interface ErrorHandler {
111
/**
112
* Handle non-fatal warnings during parsing
113
* @param message Warning message
114
*/
115
warning?: (message: string) => void;
116
117
/**
118
* Handle recoverable errors during parsing
119
* @param message Error message
120
*/
121
error?: (message: string) => void;
122
123
/**
124
* Handle fatal errors that stop parsing
125
* @param message Fatal error message
126
*/
127
fatalError?: (message: string) => void;
128
}
129
130
/**
131
* Alternative function-based error handler
132
* @param level The error level ('warning', 'error', or 'fatalError')
133
* @param message The error message
134
*/
135
type ErrorHandlerFunction = (level: string, message: string) => void;
136
137
/**
138
* ParseError class for XML parsing errors with location information
139
*/
140
class ParseError extends Error {
141
constructor(message: string, locator?: object);
142
readonly name: 'ParseError';
143
}
144
```
145
146
**Usage Examples:**
147
148
```javascript
149
const { DOMParser } = require('xmldom');
150
151
// Collect all parsing issues
152
const issues = [];
153
const parser = new DOMParser({
154
errorHandler: {
155
warning: function(msg) {
156
issues.push({ level: 'warning', message: msg });
157
},
158
error: function(msg) {
159
issues.push({ level: 'error', message: msg });
160
},
161
fatalError: function(msg) {
162
issues.push({ level: 'fatal', message: msg });
163
throw new Error(`Fatal XML Error: ${msg}`);
164
}
165
}
166
});
167
168
// Parse problematic XML
169
try {
170
const doc = parser.parseFromString(`
171
<root>
172
<unclosed-tag>
173
<invalid-&-entity>content</invalid-&-entity>
174
<duplicate id="1">
175
<item id="1">conflict</item>
176
</duplicate>
177
</root>
178
`, 'text/xml');
179
180
console.log('Parsing completed with issues:');
181
issues.forEach(issue => {
182
console.log(`${issue.level.toUpperCase()}: ${issue.message}`);
183
});
184
} catch (error) {
185
console.log('Parsing failed:', error.message);
186
console.log('Issues found:', issues);
187
}
188
189
// Function-style error handler with custom logic
190
const strictParser = new DOMParser({
191
errorHandler: function(level, msg) {
192
const timestamp = new Date().toISOString();
193
const logMessage = `[${timestamp}] XML ${level.toUpperCase()}: ${msg}`;
194
195
switch (level) {
196
case 'warning':
197
console.warn(logMessage);
198
break;
199
case 'error':
200
console.error(logMessage);
201
// Convert errors to fatal in strict mode
202
throw new Error(`Strict mode: ${msg}`);
203
case 'fatalError':
204
console.error(logMessage);
205
throw new Error(`Fatal: ${msg}`);
206
}
207
}
208
});
209
210
// Position-aware error handling
211
const positionParser = new DOMParser({
212
locator: {},
213
errorHandler: function(level, msg) {
214
// Error messages include position information when locator is enabled
215
console.log(`${level}: ${msg}`);
216
// Message format: "[xmldom error] message @file#[line:X,col:Y]"
217
}
218
});
219
```
220
221
### DOM Operation Error Scenarios
222
223
Common scenarios where DOMExceptions are thrown during DOM manipulation.
224
225
**Usage Examples:**
226
227
```javascript
228
const { DOMParser, DOMException } = require('xmldom');
229
const parser = new DOMParser();
230
const doc = parser.parseFromString('<root></root>', 'text/xml');
231
232
// HIERARCHY_REQUEST_ERR - Invalid parent-child relationships
233
try {
234
const element = doc.createElement('test');
235
element.appendChild(element); // Cannot append element to itself
236
} catch (e) {
237
console.log(`Hierarchy error: ${e.message}`);
238
}
239
240
try {
241
doc.documentElement.appendChild(doc); // Cannot append document to element
242
} catch (e) {
243
console.log(`Hierarchy error: ${e.message}`);
244
}
245
246
// WRONG_DOCUMENT_ERR - Using nodes from different documents
247
try {
248
const otherDoc = parser.parseFromString('<other></other>', 'text/xml');
249
doc.documentElement.appendChild(otherDoc.documentElement);
250
} catch (e) {
251
console.log(`Wrong document error: ${e.message}`);
252
}
253
254
// INVALID_CHARACTER_ERR - Invalid names
255
try {
256
doc.createElement('123invalid'); // Names cannot start with digits
257
} catch (e) {
258
console.log(`Invalid character error: ${e.message}`);
259
}
260
261
try {
262
doc.createElement('invalid name'); // Names cannot contain spaces
263
} catch (e) {
264
console.log(`Invalid character error: ${e.message}`);
265
}
266
267
// NOT_FOUND_ERR - Removing non-existent nodes
268
try {
269
const parent = doc.createElement('parent');
270
const child = doc.createElement('child');
271
parent.removeChild(child); // Child is not actually a child of parent
272
} catch (e) {
273
console.log(`Not found error: ${e.message}`);
274
}
275
276
// INUSE_ATTRIBUTE_ERR - Attribute already in use
277
try {
278
const element1 = doc.createElement('element1');
279
const element2 = doc.createElement('element2');
280
const attr = doc.createAttribute('test');
281
282
element1.setAttributeNode(attr);
283
element2.setAttributeNode(attr); // Attribute already belongs to element1
284
} catch (e) {
285
console.log(`Attribute in use error: ${e.message}`);
286
}
287
288
// NAMESPACE_ERR - Invalid namespace operations
289
try {
290
doc.createElementNS('', 'prefix:name'); // Empty namespace with prefix
291
} catch (e) {
292
console.log(`Namespace error: ${e.message}`);
293
}
294
295
try {
296
doc.createElementNS('http://example.com', 'xml:test'); // Reserved xml prefix
297
} catch (e) {
298
console.log(`Namespace error: ${e.message}`);
299
}
300
```
301
302
### Custom Error Handler Patterns
303
304
Advanced patterns for handling parsing errors in different application contexts.
305
306
**Usage Examples:**
307
308
```javascript
309
const { DOMParser } = require('xmldom');
310
311
// Validation-focused error handler
312
class XMLValidator {
313
constructor() {
314
this.warnings = [];
315
this.errors = [];
316
this.isValid = true;
317
}
318
319
createParser() {
320
return new DOMParser({
321
errorHandler: {
322
warning: (msg) => {
323
this.warnings.push(msg);
324
},
325
error: (msg) => {
326
this.errors.push(msg);
327
this.isValid = false;
328
},
329
fatalError: (msg) => {
330
this.errors.push(msg);
331
this.isValid = false;
332
throw new Error(`XML Validation Failed: ${msg}`);
333
}
334
}
335
});
336
}
337
338
validate(xmlString) {
339
this.warnings = [];
340
this.errors = [];
341
this.isValid = true;
342
343
try {
344
const parser = this.createParser();
345
const doc = parser.parseFromString(xmlString, 'text/xml');
346
return {
347
isValid: this.isValid,
348
document: doc,
349
warnings: this.warnings,
350
errors: this.errors
351
};
352
} catch (error) {
353
return {
354
isValid: false,
355
document: null,
356
warnings: this.warnings,
357
errors: [...this.errors, error.message]
358
};
359
}
360
}
361
}
362
363
// Usage
364
const validator = new XMLValidator();
365
const result = validator.validate('<root><unclosed></root>');
366
console.log('Valid:', result.isValid);
367
console.log('Errors:', result.errors);
368
369
// Logging-focused error handler with different output targets
370
class XMLLogger {
371
constructor(options = {}) {
372
this.logWarnings = options.logWarnings !== false;
373
this.logErrors = options.logErrors !== false;
374
this.throwOnError = options.throwOnError || false;
375
this.logger = options.logger || console;
376
}
377
378
createParser() {
379
return new DOMParser({
380
errorHandler: {
381
warning: (msg) => {
382
if (this.logWarnings) {
383
this.logger.warn(`XML Warning: ${msg}`);
384
}
385
},
386
error: (msg) => {
387
if (this.logErrors) {
388
this.logger.error(`XML Error: ${msg}`);
389
}
390
if (this.throwOnError) {
391
throw new Error(`XML Error: ${msg}`);
392
}
393
},
394
fatalError: (msg) => {
395
this.logger.error(`XML Fatal Error: ${msg}`);
396
throw new Error(`XML Fatal Error: ${msg}`);
397
}
398
}
399
});
400
}
401
}
402
403
// Usage with custom logger
404
const customLogger = {
405
warn: (msg) => console.log(`[WARN] ${new Date().toISOString()} ${msg}`),
406
error: (msg) => console.log(`[ERROR] ${new Date().toISOString()} ${msg}`)
407
};
408
409
const logger = new XMLLogger({
410
logger: customLogger,
411
throwOnError: true
412
});
413
414
// Silent parser that collects errors without logging
415
const silentIssues = [];
416
const silentParser = new DOMParser({
417
errorHandler: (level, msg) => {
418
silentIssues.push({ level, message: msg, timestamp: Date.now() });
419
}
420
});
421
422
const doc = silentParser.parseFromString('<root><problem>', 'text/xml');
423
console.log('Silent parsing issues:', silentIssues);
424
```
425
426
### Error Recovery Strategies
427
428
Strategies for handling and recovering from parsing errors in robust applications.
429
430
**Usage Examples:**
431
432
```javascript
433
const { DOMParser } = require('xmldom');
434
435
// Fallback parsing with progressively more lenient settings
436
function robustParse(xmlString) {
437
const strategies = [
438
// Strategy 1: Strict parsing
439
() => {
440
const parser = new DOMParser({
441
errorHandler: {
442
warning: () => {}, // Ignore warnings
443
error: (msg) => { throw new Error(msg); },
444
fatalError: (msg) => { throw new Error(msg); }
445
}
446
});
447
return parser.parseFromString(xmlString, 'text/xml');
448
},
449
450
// Strategy 2: Warning-tolerant parsing
451
() => {
452
const parser = new DOMParser({
453
errorHandler: {
454
warning: () => {}, // Ignore warnings
455
error: () => {}, // Ignore errors
456
fatalError: (msg) => { throw new Error(msg); }
457
}
458
});
459
return parser.parseFromString(xmlString, 'text/xml');
460
},
461
462
// Strategy 3: HTML parsing mode (more lenient)
463
() => {
464
const parser = new DOMParser({
465
errorHandler: () => {} // Ignore all issues
466
});
467
return parser.parseFromString(xmlString, 'text/html');
468
}
469
];
470
471
const errors = [];
472
473
for (let i = 0; i < strategies.length; i++) {
474
try {
475
const doc = strategies[i]();
476
return {
477
success: true,
478
document: doc,
479
strategy: i + 1,
480
errors: errors
481
};
482
} catch (error) {
483
errors.push(`Strategy ${i + 1}: ${error.message}`);
484
}
485
}
486
487
return {
488
success: false,
489
document: null,
490
strategy: null,
491
errors: errors
492
};
493
}
494
495
// Usage
496
const problematicXML = '<root><unclosed><invalid&entity>content</root>';
497
const result = robustParse(problematicXML);
498
499
if (result.success) {
500
console.log(`Parsed successfully using strategy ${result.strategy}`);
501
console.log('Document:', result.document.toString());
502
} else {
503
console.log('All parsing strategies failed');
504
result.errors.forEach(error => console.log('Error:', error));
505
}
506
```