CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-xml2js

Simple XML to JavaScript object converter.

Overview
Eval results
Files

processing.mddocs/

Text Processing

Built-in text processing functions for common XML data transformations including normalization, type conversion, and namespace handling.

Capabilities

Processors Module

The processors module provides built-in text processing functions that can be used with parser and builder options to transform XML data during parsing.

const processors: {
  normalize: (str: string) => string;
  firstCharLowerCase: (str: string) => string;
  stripPrefix: (str: string) => string;
  parseNumbers: (str: string) => string | number;
  parseBooleans: (str: string) => string | boolean;
};

Usage Examples:

const xml2js = require('xml2js');

// Access processors
const { processors } = xml2js;

// Use processors individually
console.log(processors.normalize('HELLO WORLD')); // 'hello world'
console.log(processors.firstCharLowerCase('UserName')); // 'userName'
console.log(processors.stripPrefix('ns:ElementName')); // 'ElementName'
console.log(processors.parseNumbers('42')); // 42 (number)
console.log(processors.parseBooleans('true')); // true (boolean)

// Use with parser options
const parserOptions = {
  tagNameProcessors: [processors.firstCharLowerCase],
  valueProcessors: [processors.parseNumbers, processors.parseBooleans],
  attrNameProcessors: [processors.normalize]
};

const parser = new xml2js.Parser(parserOptions);

normalize Function

Converts strings to lowercase for case-insensitive processing.

/**
 * Convert string to lowercase
 * @param str - Input string to normalize
 * @returns Lowercase string
 */
function normalize(str: string): string;

Usage Examples:

const xml2js = require('xml2js');

// Direct usage
const result = xml2js.processors.normalize('PRODUCT');
console.log(result); // 'product'

// In parser configuration
const options = {
  tagNameProcessors: [xml2js.processors.normalize],
  attrNameProcessors: [xml2js.processors.normalize]
};

const xmlString = '<PRODUCT ID="123"><NAME>Item</NAME></PRODUCT>';
xml2js.parseString(xmlString, options, (err, result) => {
  if (!err) {
    console.log(result); // Tags and attributes converted to lowercase
  }
});

firstCharLowerCase Function

Converts the first character of a string to lowercase, useful for camelCase conversion.

/**
 * Convert first character to lowercase
 * @param str - Input string to process
 * @returns String with first character in lowercase
 */
function firstCharLowerCase(str: string): string;

Usage Examples:

const xml2js = require('xml2js');

// Direct usage
console.log(xml2js.processors.firstCharLowerCase('ProductName')); // 'productName'
console.log(xml2js.processors.firstCharLowerCase('UserID')); // 'userID'
console.log(xml2js.processors.firstCharLowerCase('XMLParser')); // 'xMLParser'

// Convert XML tags to camelCase
const options = {
  tagNameProcessors: [xml2js.processors.firstCharLowerCase],
  explicitArray: false
};

const xmlString = `
  <UserProfile>
    <FirstName>John</FirstName>
    <LastName>Doe</LastName>
    <EmailAddress>john@example.com</EmailAddress>
  </UserProfile>
`;

xml2js.parseString(xmlString, options, (err, result) => {
  if (!err) {
    console.log(result);
    // Result will have camelCase property names:
    // { userProfile: { firstName: 'John', lastName: 'Doe', emailAddress: 'john@example.com' } }
  }
});

stripPrefix Function

Removes XML namespace prefixes from element and attribute names.

/**
 * Remove XML namespace prefixes
 * @param str - Input string that may contain namespace prefix
 * @returns String with namespace prefix removed
 */
function stripPrefix(str: string): string;

Usage Examples:

const xml2js = require('xml2js');

// Direct usage
console.log(xml2js.processors.stripPrefix('ns:ProductName')); // 'ProductName'
console.log(xml2js.processors.stripPrefix('soap:Envelope')); // 'Envelope'
console.log(xml2js.processors.stripPrefix('PlainElement')); // 'PlainElement' (no change)

// Strip namespaces during parsing
const options = {
  tagNameProcessors: [xml2js.processors.stripPrefix],
  attrNameProcessors: [xml2js.processors.stripPrefix],
  explicitArray: false
};

const namespacedXml = `
  <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://example.com/webservice">
    <soap:Header />
    <soap:Body>
      <web:GetUserRequest web:userId="123">
        <web:UserName>John Doe</web:UserName>
      </web:GetUserRequest>
    </soap:Body>
  </soap:Envelope>
`;

xml2js.parseString(namespacedXml, options, (err, result) => {
  if (!err) {
    console.log(result);
    // Result will have namespace prefixes stripped:
    // { Envelope: { Header: '', Body: { GetUserRequest: { UserName: 'John Doe' } } } }
  }
});

parseNumbers Function

Converts numeric strings to JavaScript numbers when possible, leaving non-numeric strings unchanged.

/**
 * Convert numeric strings to numbers
 * @param str - Input string to parse
 * @returns Number if string is numeric, original string otherwise
 */
function parseNumbers(str: string): string | number;

Usage Examples:

const xml2js = require('xml2js');

// Direct usage
console.log(xml2js.processors.parseNumbers('42')); // 42 (number)
console.log(xml2js.processors.parseNumbers('3.14159')); // 3.14159 (number)
console.log(xml2js.processors.parseNumbers('-123')); // -123 (number)
console.log(xml2js.processors.parseNumbers('0')); // 0 (number)
console.log(xml2js.processors.parseNumbers('not a number')); // 'not a number' (string)
console.log(xml2js.processors.parseNumbers('')); // '' (string)

// Parse numbers in XML values
const options = {
  valueProcessors: [xml2js.processors.parseNumbers],
  explicitArray: false
};

const xmlWithNumbers = `
  <product>
    <id>12345</id>
    <price>99.99</price>
    <quantity>0</quantity>
    <discount>-5.50</discount>
    <name>Smartphone</name>
    <active>true</active>
  </product>
`;

xml2js.parseString(xmlWithNumbers, options, (err, result) => {
  if (!err) {
    console.log(result);
    // Numbers are converted: { product: { id: 12345, price: 99.99, quantity: 0, discount: -5.5, name: 'Smartphone', active: 'true' } }
  }
});

parseBooleans Function

Converts boolean string representations to JavaScript boolean values.

/**
 * Convert boolean strings to booleans
 * @param str - Input string to parse
 * @returns Boolean if string represents true/false, original string otherwise
 */
function parseBooleans(str: string): string | boolean;

Usage Examples:

const xml2js = require('xml2js');

// Direct usage
console.log(xml2js.processors.parseBooleans('true')); // true (boolean)
console.log(xml2js.processors.parseBooleans('false')); // false (boolean)
console.log(xml2js.processors.parseBooleans('TRUE')); // true (boolean) - case insensitive
console.log(xml2js.processors.parseBooleans('False')); // false (boolean)
console.log(xml2js.processors.parseBooleans('yes')); // 'yes' (string) - not converted
console.log(xml2js.processors.parseBooleans('1')); // '1' (string) - not converted

// Parse booleans in XML values
const options = {
  valueProcessors: [xml2js.processors.parseBooleans],
  attrValueProcessors: [xml2js.processors.parseBooleans],
  explicitArray: false
};

const xmlWithBooleans = `
  <settings>
    <feature enabled="true">
      <name>Auto-save</name>
      <active>false</active>
      <visible>TRUE</visible>
    </feature>
    <debug>False</debug>
  </settings>
`;

xml2js.parseString(xmlWithBooleans, options, (err, result) => {
  if (!err) {
    console.log(result);
    // Booleans are converted: enabled, active, visible, debug become boolean values
  }
});

Combining Multiple Processors

Processors can be chained together in arrays to apply multiple transformations:

const xml2js = require('xml2js');

// Combine multiple processors
const advancedOptions = {
  // Process tag names: strip namespaces, then convert to camelCase
  tagNameProcessors: [
    xml2js.processors.stripPrefix,
    xml2js.processors.firstCharLowerCase
  ],
  
  // Process attribute names: normalize to lowercase
  attrNameProcessors: [
    xml2js.processors.normalize
  ],
  
  // Process values: parse numbers and booleans
  valueProcessors: [
    xml2js.processors.parseNumbers,
    xml2js.processors.parseBooleans
  ],
  
  // Process attribute values: parse numbers and booleans
  attrValueProcessors: [
    xml2js.processors.parseNumbers,
    xml2js.processors.parseBooleans
  ],
  
  explicitArray: false,
  mergeAttrs: true
};

const complexXml = `
  <ns:Product xmlns:ns="http://example.com/products" ID="123" Active="true">
    <ns:ProductName>Laptop Computer</ns:ProductName>
    <ns:Price Currency="USD">999.99</ns:Price>
    <ns:InStock>5</ns:InStock>
    <ns:Featured>false</ns:Featured>
  </ns:Product>
`;

xml2js.parseString(complexXml, advancedOptions, (err, result) => {
  if (!err) {
    console.log(JSON.stringify(result, null, 2));
    // Result combines all transformations:
    // - Namespace prefixes removed
    // - Tag names converted to camelCase
    // - Attribute names normalized to lowercase
    // - Numeric and boolean values properly typed
  }
});

Custom Processors

You can create custom processor functions that follow the same pattern:

const xml2js = require('xml2js');

// Custom processor to convert snake_case to camelCase
function snakeToCamel(str) {
  return str.replace(/_([a-z])/g, (match, letter) => letter.toUpperCase());
}

// Custom processor to convert units
function parseUnits(str) {
  const match = str.match(/^(\d+(?:\.\d+)?)\s*(px|em|rem|%)$/);
  if (match) {
    return {
      value: parseFloat(match[1]),
      unit: match[2]
    };
  }
  return str;
}

// Use custom processors
const customOptions = {
  tagNameProcessors: [snakeToCamel],
  valueProcessors: [parseUnits, xml2js.processors.parseNumbers],
  explicitArray: false
};

const xmlWithCustomData = `
  <css_style>
    <font_size>16px</font_size>
    <margin_top>2em</margin_top>
    <opacity>0.8</opacity>
  </css_style>
`;

xml2js.parseString(xmlWithCustomData, customOptions, (err, result) => {
  if (!err) {
    console.log(JSON.stringify(result, null, 2));
    // Custom processors applied: snake_case -> camelCase, units parsed
  }
});

Processing Order

When multiple processors are specified in an array, they are applied in order from first to last:

const xml2js = require('xml2js');

// Order matters: first strip prefix, then convert case
const options1 = {
  tagNameProcessors: [
    xml2js.processors.stripPrefix,      // First: 'ns:ProductName' -> 'ProductName'
    xml2js.processors.firstCharLowerCase // Then: 'ProductName' -> 'productName'
  ]
};

// Different order produces different results
const options2 = {
  tagNameProcessors: [
    xml2js.processors.firstCharLowerCase, // First: 'ns:ProductName' -> 'ns:productName'
    xml2js.processors.stripPrefix        // Then: 'ns:productName' -> 'productName'  
  ]
};

// Both produce the same final result in this case, but order can matter for complex transformations

Install with Tessl CLI

npx tessl i tessl/npm-xml2js

docs

building.md

configuration.md

index.md

parsing.md

processing.md

tile.json