or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

building.mdconfiguration.mdindex.mdparsing.mdprocessing.md

configuration.mddocs/

0

# Configuration

1

2

Default configuration presets and validation error handling for different API versions and usage patterns.

3

4

## Capabilities

5

6

### Default Configuration Presets

7

8

The defaults module provides version-specific configuration presets that match different API behaviors and compatibility levels.

9

10

```javascript { .api }

11

const defaults: {

12

"0.1": DefaultOptions;

13

"0.2": DefaultOptions;

14

};

15

16

interface DefaultOptions {

17

explicitArray: boolean;

18

ignoreAttrs: boolean;

19

mergeAttrs: boolean;

20

normalize: boolean;

21

normalizeTags: boolean;

22

attrkey: string;

23

charkey: string;

24

explicitCharkey: boolean;

25

trim: boolean;

26

explicitRoot: boolean;

27

emptyTag: string;

28

strict: boolean;

29

}

30

```

31

32

**Usage Examples:**

33

34

```javascript

35

const xml2js = require('xml2js');

36

37

// Access default configurations

38

console.log(xml2js.defaults['0.1']);

39

console.log(xml2js.defaults['0.2']);

40

41

// Use version-specific defaults

42

const parser01 = new xml2js.Parser(xml2js.defaults['0.1']);

43

const parser02 = new xml2js.Parser(xml2js.defaults['0.2']);

44

45

// Extend defaults with custom options

46

const customOptions = Object.assign({}, xml2js.defaults['0.2'], {

47

trim: true,

48

parseNumbers: true,

49

tagNameProcessors: [xml2js.processors.firstCharLowerCase]

50

});

51

52

const customParser = new xml2js.Parser(customOptions);

53

```

54

55

### Version 0.1 Defaults

56

57

Legacy configuration preset for backwards compatibility with older xml2js behavior.

58

59

```javascript { .api }

60

const version01Defaults: {

61

explicitArray: false;

62

ignoreAttrs: false;

63

mergeAttrs: false;

64

normalize: true;

65

normalizeTags: false;

66

attrkey: "@";

67

charkey: "#";

68

explicitCharkey: false;

69

trim: true;

70

explicitRoot: false;

71

emptyTag: "";

72

strict: true;

73

validator: null;

74

xmlns: false;

75

explicitChildren: false;

76

childkey: "@@";

77

charsAsChildren: false;

78

includeWhiteChars: false;

79

async: false;

80

attrNameProcessors: null;

81

attrValueProcessors: null;

82

tagNameProcessors: null;

83

valueProcessors: null;

84

};

85

```

86

87

**Characteristics of Version 0.1:**

88

- `explicitArray: false` - Single child elements are not wrapped in arrays

89

- `ignoreAttrs: false` - XML attributes are preserved

90

- `normalize: true` and `trim: true` - Text processing enabled by default

91

- `explicitRoot: false` - Root element not wrapped in result

92

- Different attribute/character keys: `@` for attributes, `#` for character content

93

94

**Usage Examples:**

95

96

```javascript

97

const xml2js = require('xml2js');

98

99

// Parser with 0.1 defaults

100

const legacyParser = new xml2js.Parser(xml2js.defaults['0.1']);

101

102

const xmlString = '<person name="John"><age>30</age></person>';

103

legacyParser.parseString(xmlString, (err, result) => {

104

if (!err) {

105

console.log(result);

106

// With 0.1 defaults: { person: { '@': { name: 'John' }, age: '30' } }

107

// Note: attributes preserved with @ key, no root wrapper

108

}

109

});

110

```

111

112

### Version 0.2 Defaults

113

114

Current default configuration providing more comprehensive XML handling with attribute support.

115

116

```javascript { .api }

117

const version02Defaults: {

118

explicitArray: true;

119

ignoreAttrs: false;

120

mergeAttrs: false;

121

normalize: false;

122

normalizeTags: false;

123

attrkey: "$";

124

charkey: "_";

125

explicitCharkey: false;

126

trim: false;

127

explicitRoot: true;

128

emptyTag: "";

129

strict: true;

130

validator: null;

131

xmlns: false;

132

explicitChildren: false;

133

preserveChildrenOrder: false;

134

childkey: "$$";

135

charsAsChildren: false;

136

includeWhiteChars: false;

137

async: false;

138

attrNameProcessors: null;

139

attrValueProcessors: null;

140

tagNameProcessors: null;

141

valueProcessors: null;

142

rootName: "root";

143

xmldec: {

144

version: "1.0";

145

encoding: "UTF-8";

146

standalone: true;

147

};

148

doctype: null;

149

renderOpts: {

150

pretty: true;

151

indent: " ";

152

newline: "\n";

153

};

154

headless: false;

155

chunkSize: 10000;

156

cdata: false;

157

};

158

```

159

160

**Characteristics of Version 0.2:**

161

- `explicitArray: true` - All child elements are wrapped in arrays for consistency

162

- `ignoreAttrs: false` - XML attributes are preserved and accessible

163

- More predictable structure for programmatic processing

164

165

**Usage Examples:**

166

167

```javascript

168

const xml2js = require('xml2js');

169

170

// Parser with 0.2 defaults (current default)

171

const modernParser = new xml2js.Parser(xml2js.defaults['0.2']);

172

173

const xmlString = '<person name="John"><age>30</age></person>';

174

modernParser.parseString(xmlString, (err, result) => {

175

if (!err) {

176

console.log(result);

177

// With 0.2 defaults: { person: { $: { name: 'John' }, age: ['30'] } }

178

// Note: attributes preserved, age is an array

179

}

180

});

181

```

182

183

### Custom Configuration Patterns

184

185

```javascript

186

const xml2js = require('xml2js');

187

188

// Web API friendly configuration

189

const webApiConfig = Object.assign({}, xml2js.defaults['0.2'], {

190

explicitArray: false, // Simpler structure

191

mergeAttrs: true, // Merge attributes with content

192

trim: true, // Clean whitespace

193

tagNameProcessors: [xml2js.processors.firstCharLowerCase],

194

valueProcessors: [xml2js.processors.parseNumbers, xml2js.processors.parseBooleans]

195

});

196

197

// Configuration for processing RSS/Atom feeds

198

const feedConfig = Object.assign({}, xml2js.defaults['0.2'], {

199

explicitArray: false,

200

trim: true,

201

normalize: true,

202

tagNameProcessors: [xml2js.processors.normalize],

203

valueProcessors: [xml2js.processors.parseNumbers]

204

});

205

206

// Configuration for SOAP/XML services

207

const soapConfig = Object.assign({}, xml2js.defaults['0.2'], {

208

explicitArray: false,

209

tagNameProcessors: [xml2js.processors.stripPrefix],

210

xmlns: true, // Preserve namespace information

211

explicitRoot: false

212

});

213

```

214

215

## ValidationError Class

216

217

Custom error class for XML validation and parsing failures, extending the standard JavaScript Error class.

218

219

```javascript { .api }

220

/**

221

* Custom error class for XML validation failures

222

*/

223

class ValidationError extends Error {

224

/**

225

* Create a ValidationError

226

* @param message - Error message describing the validation failure

227

*/

228

constructor(message: string);

229

}

230

```

231

232

**Usage Examples:**

233

234

```javascript

235

const xml2js = require('xml2js');

236

237

// ValidationError is thrown for validation failures

238

const parser = new xml2js.Parser({

239

validator: (xpath, currentValue, newValue) => {

240

// Custom validation logic

241

if (xpath === '/product/price' && isNaN(parseFloat(newValue))) {

242

throw new xml2js.ValidationError(`Invalid price value: ${newValue}`);

243

}

244

return newValue;

245

}

246

});

247

248

const invalidXml = '<product><price>not-a-number</price></product>';

249

250

parser.parseString(invalidXml, (err, result) => {

251

if (err instanceof xml2js.ValidationError) {

252

console.error('Validation failed:', err.message);

253

// Handle validation error specifically

254

} else if (err) {

255

console.error('Parse error:', err.message);

256

// Handle other parsing errors

257

} else {

258

console.log('Parse successful:', result);

259

}

260

});

261

262

// Using with promises

263

async function parseWithValidation(xmlString) {

264

try {

265

const result = await parser.parseStringPromise(xmlString);

266

return result;

267

} catch (error) {

268

if (error instanceof xml2js.ValidationError) {

269

console.error('Validation error:', error.message);

270

throw new Error(`XML validation failed: ${error.message}`);

271

}

272

throw error;

273

}

274

}

275

```

276

277

### Custom Validation with ValidationError

278

279

```javascript

280

const xml2js = require('xml2js');

281

282

// Complex validation example

283

function createValidatingParser(schema) {

284

return new xml2js.Parser({

285

validator: (xpath, currentValue, newValue) => {

286

const rule = schema[xpath];

287

if (rule) {

288

// Type validation

289

if (rule.type === 'number' && isNaN(parseFloat(newValue))) {

290

throw new xml2js.ValidationError(`Expected number at ${xpath}, got: ${newValue}`);

291

}

292

293

// Range validation

294

if (rule.type === 'number' && rule.min !== undefined) {

295

const numValue = parseFloat(newValue);

296

if (numValue < rule.min) {

297

throw new xml2js.ValidationError(`Value ${numValue} at ${xpath} is below minimum ${rule.min}`);

298

}

299

}

300

301

// String length validation

302

if (rule.type === 'string' && rule.maxLength !== undefined) {

303

if (newValue.length > rule.maxLength) {

304

throw new xml2js.ValidationError(`String at ${xpath} exceeds maximum length ${rule.maxLength}`);

305

}

306

}

307

308

// Required field validation

309

if (rule.required && (!newValue || newValue.trim() === '')) {

310

throw new xml2js.ValidationError(`Required field ${xpath} is empty`);

311

}

312

}

313

314

return newValue;

315

}

316

});

317

}

318

319

// Define validation schema

320

const productSchema = {

321

'/product/id': { type: 'number', required: true, min: 1 },

322

'/product/name': { type: 'string', required: true, maxLength: 100 },

323

'/product/price': { type: 'number', required: true, min: 0 },

324

'/product/description': { type: 'string', maxLength: 500 }

325

};

326

327

const validatingParser = createValidatingParser(productSchema);

328

329

// Test with valid XML

330

const validXml = `

331

<product>

332

<id>123</id>

333

<name>Laptop</name>

334

<price>999.99</price>

335

<description>High-performance laptop</description>

336

</product>

337

`;

338

339

// Test with invalid XML

340

const invalidXml = `

341

<product>

342

<id>0</id>

343

<name></name>

344

<price>-100</price>

345

<description>${'x'.repeat(600)}</description>

346

</product>

347

`;

348

349

validatingParser.parseString(validXml, (err, result) => {

350

if (err instanceof xml2js.ValidationError) {

351

console.error('Validation failed:', err.message);

352

} else if (!err) {

353

console.log('Valid XML parsed successfully');

354

}

355

});

356

```

357

358

## Configuration Best Practices

359

360

### Choosing the Right Defaults

361

362

```javascript

363

const xml2js = require('xml2js');

364

365

// For simple XML consumption (e.g., configuration files)

366

const simpleConfig = xml2js.defaults['0.1']; // No arrays, ignores attributes

367

368

// For comprehensive XML processing (e.g., APIs, complex documents)

369

const comprehensiveConfig = xml2js.defaults['0.2']; // Preserves structure

370

371

// For web applications (JSON-like structure)

372

const webConfig = Object.assign({}, xml2js.defaults['0.2'], {

373

explicitArray: false,

374

mergeAttrs: true

375

});

376

```

377

378

### Performance Considerations

379

380

```javascript

381

const xml2js = require('xml2js');

382

383

// High-performance parsing for large documents

384

const performanceConfig = {

385

// Minimal processing

386

explicitArray: false,

387

ignoreAttrs: true,

388

trim: false,

389

normalize: false,

390

391

// No text processors to avoid overhead

392

tagNameProcessors: null,

393

valueProcessors: null,

394

395

// Async processing for large documents

396

async: true,

397

chunkSize: 50000

398

};

399

400

// Memory-efficient parsing

401

const memoryEfficientConfig = {

402

explicitArray: false,

403

explicitRoot: false,

404

trim: true,

405

emptyTag: null, // Don't create empty values

406

strict: false // More lenient parsing

407

};

408

```

409

410

### Error Handling Strategies

411

412

```javascript

413

const xml2js = require('xml2js');

414

415

// Comprehensive error handling

416

function createRobustParser(options = {}) {

417

const defaultOptions = Object.assign({}, xml2js.defaults['0.2'], {

418

// Enable strict validation

419

strict: true,

420

421

// Custom validator for business logic

422

validator: (xpath, currentValue, newValue) => {

423

try {

424

// Apply custom validation rules here

425

return newValue;

426

} catch (validationError) {

427

throw new xml2js.ValidationError(`Validation failed at ${xpath}: ${validationError.message}`);

428

}

429

}

430

}, options);

431

432

return new xml2js.Parser(defaultOptions);

433

}

434

435

// Usage with comprehensive error handling

436

async function safeParseXML(xmlString, options) {

437

const parser = createRobustParser(options);

438

439

try {

440

const result = await parser.parseStringPromise(xmlString);

441

return { success: true, data: result };

442

} catch (error) {

443

if (error instanceof xml2js.ValidationError) {

444

return {

445

success: false,

446

error: 'validation',

447

message: error.message

448

};

449

} else {

450

return {

451

success: false,

452

error: 'parsing',

453

message: error.message

454

};

455

}

456

}

457

}

458

```