0
# Text Processing
1
2
Built-in text processing functions for common XML data transformations including normalization, type conversion, and namespace handling.
3
4
## Capabilities
5
6
### Processors Module
7
8
The processors module provides built-in text processing functions that can be used with parser and builder options to transform XML data during parsing.
9
10
```javascript { .api }
11
const processors: {
12
normalize: (str: string) => string;
13
firstCharLowerCase: (str: string) => string;
14
stripPrefix: (str: string) => string;
15
parseNumbers: (str: string) => string | number;
16
parseBooleans: (str: string) => string | boolean;
17
};
18
```
19
20
**Usage Examples:**
21
22
```javascript
23
const xml2js = require('xml2js');
24
25
// Access processors
26
const { processors } = xml2js;
27
28
// Use processors individually
29
console.log(processors.normalize('HELLO WORLD')); // 'hello world'
30
console.log(processors.firstCharLowerCase('UserName')); // 'userName'
31
console.log(processors.stripPrefix('ns:ElementName')); // 'ElementName'
32
console.log(processors.parseNumbers('42')); // 42 (number)
33
console.log(processors.parseBooleans('true')); // true (boolean)
34
35
// Use with parser options
36
const parserOptions = {
37
tagNameProcessors: [processors.firstCharLowerCase],
38
valueProcessors: [processors.parseNumbers, processors.parseBooleans],
39
attrNameProcessors: [processors.normalize]
40
};
41
42
const parser = new xml2js.Parser(parserOptions);
43
```
44
45
### normalize Function
46
47
Converts strings to lowercase for case-insensitive processing.
48
49
```javascript { .api }
50
/**
51
* Convert string to lowercase
52
* @param str - Input string to normalize
53
* @returns Lowercase string
54
*/
55
function normalize(str: string): string;
56
```
57
58
**Usage Examples:**
59
60
```javascript
61
const xml2js = require('xml2js');
62
63
// Direct usage
64
const result = xml2js.processors.normalize('PRODUCT');
65
console.log(result); // 'product'
66
67
// In parser configuration
68
const options = {
69
tagNameProcessors: [xml2js.processors.normalize],
70
attrNameProcessors: [xml2js.processors.normalize]
71
};
72
73
const xmlString = '<PRODUCT ID="123"><NAME>Item</NAME></PRODUCT>';
74
xml2js.parseString(xmlString, options, (err, result) => {
75
if (!err) {
76
console.log(result); // Tags and attributes converted to lowercase
77
}
78
});
79
```
80
81
### firstCharLowerCase Function
82
83
Converts the first character of a string to lowercase, useful for camelCase conversion.
84
85
```javascript { .api }
86
/**
87
* Convert first character to lowercase
88
* @param str - Input string to process
89
* @returns String with first character in lowercase
90
*/
91
function firstCharLowerCase(str: string): string;
92
```
93
94
**Usage Examples:**
95
96
```javascript
97
const xml2js = require('xml2js');
98
99
// Direct usage
100
console.log(xml2js.processors.firstCharLowerCase('ProductName')); // 'productName'
101
console.log(xml2js.processors.firstCharLowerCase('UserID')); // 'userID'
102
console.log(xml2js.processors.firstCharLowerCase('XMLParser')); // 'xMLParser'
103
104
// Convert XML tags to camelCase
105
const options = {
106
tagNameProcessors: [xml2js.processors.firstCharLowerCase],
107
explicitArray: false
108
};
109
110
const xmlString = `
111
<UserProfile>
112
<FirstName>John</FirstName>
113
<LastName>Doe</LastName>
114
<EmailAddress>john@example.com</EmailAddress>
115
</UserProfile>
116
`;
117
118
xml2js.parseString(xmlString, options, (err, result) => {
119
if (!err) {
120
console.log(result);
121
// Result will have camelCase property names:
122
// { userProfile: { firstName: 'John', lastName: 'Doe', emailAddress: 'john@example.com' } }
123
}
124
});
125
```
126
127
### stripPrefix Function
128
129
Removes XML namespace prefixes from element and attribute names.
130
131
```javascript { .api }
132
/**
133
* Remove XML namespace prefixes
134
* @param str - Input string that may contain namespace prefix
135
* @returns String with namespace prefix removed
136
*/
137
function stripPrefix(str: string): string;
138
```
139
140
**Usage Examples:**
141
142
```javascript
143
const xml2js = require('xml2js');
144
145
// Direct usage
146
console.log(xml2js.processors.stripPrefix('ns:ProductName')); // 'ProductName'
147
console.log(xml2js.processors.stripPrefix('soap:Envelope')); // 'Envelope'
148
console.log(xml2js.processors.stripPrefix('PlainElement')); // 'PlainElement' (no change)
149
150
// Strip namespaces during parsing
151
const options = {
152
tagNameProcessors: [xml2js.processors.stripPrefix],
153
attrNameProcessors: [xml2js.processors.stripPrefix],
154
explicitArray: false
155
};
156
157
const namespacedXml = `
158
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://example.com/webservice">
159
<soap:Header />
160
<soap:Body>
161
<web:GetUserRequest web:userId="123">
162
<web:UserName>John Doe</web:UserName>
163
</web:GetUserRequest>
164
</soap:Body>
165
</soap:Envelope>
166
`;
167
168
xml2js.parseString(namespacedXml, options, (err, result) => {
169
if (!err) {
170
console.log(result);
171
// Result will have namespace prefixes stripped:
172
// { Envelope: { Header: '', Body: { GetUserRequest: { UserName: 'John Doe' } } } }
173
}
174
});
175
```
176
177
### parseNumbers Function
178
179
Converts numeric strings to JavaScript numbers when possible, leaving non-numeric strings unchanged.
180
181
```javascript { .api }
182
/**
183
* Convert numeric strings to numbers
184
* @param str - Input string to parse
185
* @returns Number if string is numeric, original string otherwise
186
*/
187
function parseNumbers(str: string): string | number;
188
```
189
190
**Usage Examples:**
191
192
```javascript
193
const xml2js = require('xml2js');
194
195
// Direct usage
196
console.log(xml2js.processors.parseNumbers('42')); // 42 (number)
197
console.log(xml2js.processors.parseNumbers('3.14159')); // 3.14159 (number)
198
console.log(xml2js.processors.parseNumbers('-123')); // -123 (number)
199
console.log(xml2js.processors.parseNumbers('0')); // 0 (number)
200
console.log(xml2js.processors.parseNumbers('not a number')); // 'not a number' (string)
201
console.log(xml2js.processors.parseNumbers('')); // '' (string)
202
203
// Parse numbers in XML values
204
const options = {
205
valueProcessors: [xml2js.processors.parseNumbers],
206
explicitArray: false
207
};
208
209
const xmlWithNumbers = `
210
<product>
211
<id>12345</id>
212
<price>99.99</price>
213
<quantity>0</quantity>
214
<discount>-5.50</discount>
215
<name>Smartphone</name>
216
<active>true</active>
217
</product>
218
`;
219
220
xml2js.parseString(xmlWithNumbers, options, (err, result) => {
221
if (!err) {
222
console.log(result);
223
// Numbers are converted: { product: { id: 12345, price: 99.99, quantity: 0, discount: -5.5, name: 'Smartphone', active: 'true' } }
224
}
225
});
226
```
227
228
### parseBooleans Function
229
230
Converts boolean string representations to JavaScript boolean values.
231
232
```javascript { .api }
233
/**
234
* Convert boolean strings to booleans
235
* @param str - Input string to parse
236
* @returns Boolean if string represents true/false, original string otherwise
237
*/
238
function parseBooleans(str: string): string | boolean;
239
```
240
241
**Usage Examples:**
242
243
```javascript
244
const xml2js = require('xml2js');
245
246
// Direct usage
247
console.log(xml2js.processors.parseBooleans('true')); // true (boolean)
248
console.log(xml2js.processors.parseBooleans('false')); // false (boolean)
249
console.log(xml2js.processors.parseBooleans('TRUE')); // true (boolean) - case insensitive
250
console.log(xml2js.processors.parseBooleans('False')); // false (boolean)
251
console.log(xml2js.processors.parseBooleans('yes')); // 'yes' (string) - not converted
252
console.log(xml2js.processors.parseBooleans('1')); // '1' (string) - not converted
253
254
// Parse booleans in XML values
255
const options = {
256
valueProcessors: [xml2js.processors.parseBooleans],
257
attrValueProcessors: [xml2js.processors.parseBooleans],
258
explicitArray: false
259
};
260
261
const xmlWithBooleans = `
262
<settings>
263
<feature enabled="true">
264
<name>Auto-save</name>
265
<active>false</active>
266
<visible>TRUE</visible>
267
</feature>
268
<debug>False</debug>
269
</settings>
270
`;
271
272
xml2js.parseString(xmlWithBooleans, options, (err, result) => {
273
if (!err) {
274
console.log(result);
275
// Booleans are converted: enabled, active, visible, debug become boolean values
276
}
277
});
278
```
279
280
## Combining Multiple Processors
281
282
Processors can be chained together in arrays to apply multiple transformations:
283
284
```javascript
285
const xml2js = require('xml2js');
286
287
// Combine multiple processors
288
const advancedOptions = {
289
// Process tag names: strip namespaces, then convert to camelCase
290
tagNameProcessors: [
291
xml2js.processors.stripPrefix,
292
xml2js.processors.firstCharLowerCase
293
],
294
295
// Process attribute names: normalize to lowercase
296
attrNameProcessors: [
297
xml2js.processors.normalize
298
],
299
300
// Process values: parse numbers and booleans
301
valueProcessors: [
302
xml2js.processors.parseNumbers,
303
xml2js.processors.parseBooleans
304
],
305
306
// Process attribute values: parse numbers and booleans
307
attrValueProcessors: [
308
xml2js.processors.parseNumbers,
309
xml2js.processors.parseBooleans
310
],
311
312
explicitArray: false,
313
mergeAttrs: true
314
};
315
316
const complexXml = `
317
<ns:Product xmlns:ns="http://example.com/products" ID="123" Active="true">
318
<ns:ProductName>Laptop Computer</ns:ProductName>
319
<ns:Price Currency="USD">999.99</ns:Price>
320
<ns:InStock>5</ns:InStock>
321
<ns:Featured>false</ns:Featured>
322
</ns:Product>
323
`;
324
325
xml2js.parseString(complexXml, advancedOptions, (err, result) => {
326
if (!err) {
327
console.log(JSON.stringify(result, null, 2));
328
// Result combines all transformations:
329
// - Namespace prefixes removed
330
// - Tag names converted to camelCase
331
// - Attribute names normalized to lowercase
332
// - Numeric and boolean values properly typed
333
}
334
});
335
```
336
337
## Custom Processors
338
339
You can create custom processor functions that follow the same pattern:
340
341
```javascript
342
const xml2js = require('xml2js');
343
344
// Custom processor to convert snake_case to camelCase
345
function snakeToCamel(str) {
346
return str.replace(/_([a-z])/g, (match, letter) => letter.toUpperCase());
347
}
348
349
// Custom processor to convert units
350
function parseUnits(str) {
351
const match = str.match(/^(\d+(?:\.\d+)?)\s*(px|em|rem|%)$/);
352
if (match) {
353
return {
354
value: parseFloat(match[1]),
355
unit: match[2]
356
};
357
}
358
return str;
359
}
360
361
// Use custom processors
362
const customOptions = {
363
tagNameProcessors: [snakeToCamel],
364
valueProcessors: [parseUnits, xml2js.processors.parseNumbers],
365
explicitArray: false
366
};
367
368
const xmlWithCustomData = `
369
<css_style>
370
<font_size>16px</font_size>
371
<margin_top>2em</margin_top>
372
<opacity>0.8</opacity>
373
</css_style>
374
`;
375
376
xml2js.parseString(xmlWithCustomData, customOptions, (err, result) => {
377
if (!err) {
378
console.log(JSON.stringify(result, null, 2));
379
// Custom processors applied: snake_case -> camelCase, units parsed
380
}
381
});
382
```
383
384
## Processing Order
385
386
When multiple processors are specified in an array, they are applied in order from first to last:
387
388
```javascript
389
const xml2js = require('xml2js');
390
391
// Order matters: first strip prefix, then convert case
392
const options1 = {
393
tagNameProcessors: [
394
xml2js.processors.stripPrefix, // First: 'ns:ProductName' -> 'ProductName'
395
xml2js.processors.firstCharLowerCase // Then: 'ProductName' -> 'productName'
396
]
397
};
398
399
// Different order produces different results
400
const options2 = {
401
tagNameProcessors: [
402
xml2js.processors.firstCharLowerCase, // First: 'ns:ProductName' -> 'ns:productName'
403
xml2js.processors.stripPrefix // Then: 'ns:productName' -> 'productName'
404
]
405
};
406
407
// Both produce the same final result in this case, but order can matter for complex transformations
408
```