A modern ESM library for bidirectional XML to JSON conversion with comprehensive support for namespaces, CDATA sections, comments, processing instructions, and more.
- Bidirectional Conversion: Convert XML to JSON and back with high fidelity
- Complete Node Type Support:
- Elements with text content
- Attributes
- Namespaces and prefixes
- CDATA sections
- Comments
- Processing instructions
- Configurable Output: Customize JSON property names and output options
- Value Transformers: Apply type conversions (string → number, boolean, etc.)
- Path Navigation: Extract values using simple dot-notation paths
- Cross-Platform: Works in both browser and Node.js environments
- No Dependencies: Zero production dependencies by default
- TypeScript: Full TypeScript support with comprehensive type definitions
- ESM & UMD: Modern ESM modules with UMD fallback for wider compatibility
You can install XJX via npm and bundle it with your application:
npm install xjxOr use a CDN for direct browser usage:
<!-- UMD build (for browsers with global XJX variable) -->
<script src="https://unpkg.com/xjx@3.0.0/dist/xjx.umd.js"></script>
<!-- Or minified version -->
<script src="https://unpkg.com/xjx@3.0.0/dist/xjx.min.js"></script>XJX uses DOM APIs and requires a DOM implementation in Node.js environments. By default, it uses JSDOM:
npm install xjx jsdomJSDOM is a peer dependency that is marked as optional. You'll need to install it separately for Node.js usage.
If you prefer to use an alternative DOM implementation, you can use @xmldom/xmldom:
npm install xjx @xmldom/xmldomXJX will automatically detect and use one of these DOM implementations in Node.js environments.
Converting between XML and JSON is straightforward:
import { XJX } from 'xjx';
// Create an instance of XJX with default configuration
const xjx = new XJX();
// Sample XML string
const xmlString = `
<library>
<book id="b1" available="true">
<title>The Great Gatsby</title>
<author>F. Scott Fitzgerald</author>
<year>1925</year>
<description><![CDATA[A novel set in the Jazz Age]]></description>
</book>
</library>`;
// Convert XML to JSON
const jsonObj = xjx.xmlToJson(xmlString);
console.log(JSON.stringify(jsonObj, null, 2));
// Extract specific values using path navigation
const bookTitle = xjx.getPath(jsonObj, 'library.book.title.$val');
console.log(`Book title: ${bookTitle}`); // "The Great Gatsby"
// Convert JSON back to XML
const newXml = xjx.jsonToXml(jsonObj);
console.log(newXml);
// Clean up when done (important for Node.js environments)
xjx.cleanup();XJX is highly configurable. Here's an overview of the available configuration options:
const config = {
// Features to preserve during transformation
preserveNamespaces: true, // Preserve namespace information
preserveComments: true, // Preserve XML comments
preserveProcessingInstr: true, // Preserve processing instructions
preserveCDATA: true, // Preserve CDATA sections
preserveTextNodes: true, // Preserve text nodes
preserveWhitespace: false, // Preserve whitespace-only text nodes
preserveAttributes: true, // Preserve element attributes
// Output options
outputOptions: {
prettyPrint: true, // Format XML output with indentation
indent: 2, // Indentation spaces for pretty printing
compact: true, // Remove empty/undefined properties
json: {}, // Custom JSON serialization options
xml: {
declaration: true, // Include XML declaration in output
},
},
// Property names in the JSON representation
propNames: {
namespace: "$ns", // Namespace URI property
prefix: "$pre", // Namespace prefix property
attributes: "$attr", // Attributes collection property
value: "$val", // Text value property
cdata: "$cdata", // CDATA content property
comments: "$cmnt", // Comments property
instruction: "$pi", // Processing instruction property
target: "$trgt", // PI target property
children: "$children", // Child nodes collection property
},
// Optional value transformers
valueTransforms: [
// Array of transformer instances (see Value Transformers section)
]
};
// Create an instance with custom configuration
const xjx = new XJX(config);You can pass a partial configuration to override just the options you need:
// Override only specific options
const xjx = new XJX({
preserveWhitespace: true,
outputOptions: {
prettyPrint: false,
}
});XJX provides comprehensive support for XML namespaces:
<root xmlns="http://default-ns.com" xmlns:ns="http://example.org">
<ns:item id="123">Content</ns:item>
</root>The resulting JSON maintains namespace information:
{
"root": {
"$ns": "http://default-ns.com",
"$children": [
{
"item": {
"$ns": "http://example.org",
"$pre": "ns",
"$attr": [
{ "id": { "$val": "123" } }
],
"$val": "Content"
}
}
]
}
}When converting back to XML, namespace declarations and prefixes are preserved.
Value transformers allow automatic conversion between string values in XML and typed values in JSON. For example, you can convert numeric strings to actual numbers or boolean strings to boolean values.
XJX comes with several built-in transformers:
Converts strings like "true" and "false" to actual boolean values.
import { XJX, BooleanTransformer } from 'xjx';
const xjx = new XJX();
xjx.addTransformer(new BooleanTransformer({
trueValues: ['true', 'yes', '1'],
falseValues: ['false', 'no', '0']
}));Converts numeric strings to actual number values.
import { XJX, NumberTransformer } from 'xjx';
const xjx = new XJX();
xjx.addTransformer(new NumberTransformer({
parseIntegers: true,
parseFloats: true,
integerFormat: /^-?\d+$/,
floatFormat: /^-?\d*\.\d+$/
}));Applies regex-based string replacements.
import { XJX, StringReplaceTransformer } from 'xjx';
const xjx = new XJX();
xjx.addTransformer(new StringReplaceTransformer({
pattern: '/\\s+/g', // Remove whitespace
replacement: ''
}));You can create custom transformers by extending the ValueTransformer base class:
import { XJX, ValueTransformer, TransformContext } from 'xjx';
class DateTransformer extends ValueTransformer {
// XML to JSON transformation
protected xmlToJson(value, context) {
if (typeof value !== 'string') return value;
// Convert ISO date strings to Date objects
if (/^\d{4}-\d{2}-\d{2}$/.test(value)) {
return new Date(value);
}
return value;
}
// JSON to XML transformation
protected jsonToXml(value, context) {
if (value instanceof Date) {
// Format date as ISO string
return value.toISOString().split('T')[0];
}
return value;
}
}
const xjx = new XJX();
xjx.addTransformer(new DateTransformer());const xjx = new XJX(config);Creates a new XJX instance with optional configuration.
Converts an XML string to a JSON object.
const jsonObj = xjx.xmlToJson(xmlString);Converts a JSON object (in XJX format) to an XML string.
const xmlString = xjx.jsonToXml(jsonObj);Retrieves a value from a JSON object using dot notation path.
const value = xjx.getPath(jsonObj, 'root.item.title.$val', 'Default');Formats an XML string with proper indentation.
const formattedXml = xjx.prettyPrintXml(xmlString);Checks if an XML string is well-formed.
const result = xjx.validateXML(xmlString);
if (result.isValid) {
console.log('XML is valid');
} else {
console.error(`XML is invalid: ${result.message}`);
}Adds a value transformer to the configuration.
xjx.addTransformer(new NumberTransformer());Removes all value transformers from the configuration.
xjx.clearTransformers();Releases any resources, especially important in Node.js environments.
xjx.cleanup();The getPath method provides a powerful way to extract values from the XML-JSON structure using dot notation. It handles array traversal and special XML structures automatically:
xjx.getPath(jsonObj, 'path.to.value', defaultValue);Key features:
- Dot Notation: Navigate through nested objects using dot notation (e.g.,
library.book.title.$val) - Array Traversal: Automatically traverses arrays and collects matching values
- Index Access: Access specific array elements with numeric indices (e.g.,
library.book.0.title.$val) - Special XML Properties: Access XML-specific properties using configured property names (
$val,$attr, etc.) - Default Values: Specify a fallback value if the path doesn't exist
Examples:
// Get a simple text value
const title = xjx.getPath(jsonObj, 'library.book.title.$val');
// Get an attribute value
const id = xjx.getPath(jsonObj, 'library.book.$attr.0.id.$val');
// Get values from all books in an array
const authors = xjx.getPath(jsonObj, 'library.book.author.$val');
// Result: ['F. Scott Fitzgerald', 'Harper Lee', ...]
// Get a specific book by index
const secondBook = xjx.getPath(jsonObj, 'library.book.1');
// Provide a default value if path doesn't exist
const publisher = xjx.getPath(jsonObj, 'library.book.publisher.$val', 'Unknown');The JSONUtil class includes a generateJsonSchema method that creates a JSON Schema for the XJX JSON format based on the current configuration:
const jsonUtil = new JSONUtil(config);
const schema = jsonUtil.generateJsonSchema();The generated schema:
- Reflects current configuration settings (property names, preserved features)
- Includes proper type information for all properties
- Supports recursive element structures
- Documents the purpose of each property
- Can be used for validation with standard JSON Schema validators
This is useful for:
- Validating XJX JSON structures
- Generating documentation
- Providing hints in IDEs that support JSON Schema
- Data validation in applications
The library provides a utility method to convert standard JSON objects to the XJX format:
const jsonUtil = new JSONUtil(config);
const xjxJson = jsonUtil.fromJsonObject(standardJson, rootElementName);This transforms a standard JSON object:
{
"name": "John",
"age": 30,
"roles": ["admin", "user"]
}Into the XJX format:
{
"user": {
"$children": [
{ "name": { "$val": "John" } },
{ "age": { "$val": 30 } },
{
"roles": {
"$children": [
{ "$val": "admin" },
{ "$val": "user" }
]
}
}
]
}
}This is useful when you want to convert arbitrary JSON data to XML. The second parameter allows you to specify the root element name (in this example, "user").
MIT