Skip to content

Converter - Getting Started

The StAX-XML Converter provides a declarative, Zod-style API for parsing XML documents with full type safety and XPath support.

The converter is a high-level XML parsing API that allows you to:

  • Define type-safe schemas using a fluent builder API
  • Select elements with XPath for precise element targeting
  • Validate data with built-in validation methods
  • Transform results with post-processing functions
  • Infer TypeScript types automatically from schemas

Unlike the low-level event-based StaxXmlParser, the converter provides a declarative way to extract structured data from XML.

The converter is included in the stax-xml package and can be imported separately:

import { x } from 'stax-xml/converter';

Or import specific types:

import { x, type Infer, XmlParseError } from 'stax-xml/converter';

Here’s a simple example of parsing a book XML document:

import { x, type Infer } from 'stax-xml/converter';
// Define the schema
const bookSchema = x.object({
title: x.string().xpath('/book/title'),
author: x.string().xpath('/book/author'),
year: x.number().xpath('/book/year'),
price: x.number().xpath('/book/price').min(0)
});
// Infer TypeScript type
type Book = Infer<typeof bookSchema>;
// { title: string; author: string; year: number; price: number; }
// Parse XML
const xml = `
<book>
<title>The Great Gatsby</title>
<author>F. Scott Fitzgerald</author>
<year>1925</year>
<price>10.99</price>
</book>
`;
const book = bookSchema.parseSync(xml);
console.log(book);
// {
// title: "The Great Gatsby",
// author: "F. Scott Fitzgerald",
// year: 1925,
// price: 10.99
// }

The converter provides full TypeScript type inference. Your IDE will know exactly what shape your parsed data has:

const schema = x.object({
name: x.string().xpath('//name'),
count: x.number().xpath('//count')
});
const result = schema.parseSync(xml);
// TypeScript knows: { name: string; count: number; }

Use XPath expressions to precisely target elements in your XML:

// Absolute paths
x.string().xpath('/root/element')
// Descendant search
x.string().xpath('//element')
// Attributes
x.string().xpath('/@id')
// Predicates
x.array(x.object({...}), '//book[@category="fiction"]')

Built-in validation methods ensure your data meets requirements:

const schema = x.object({
age: x.number().xpath('//age').min(0).max(120).int(),
email: x.string().xpath('//email'),
score: x.number().xpath('//score').min(0).max(100)
});

Transform parsed data with custom functions:

const schema = x.object({
firstName: x.string().xpath('//firstName'),
lastName: x.string().xpath('//lastName')
}).transform(person => ({
fullName: `${person.firstName} ${person.lastName}`
}));
// Result: { fullName: "John Doe" }

Both synchronous and asynchronous parsing are supported:

// Synchronous
const result = schema.parseSync(xmlString);
// Asynchronous
const result = await schema.parse(xmlString);
// Safe parsing (returns error object instead of throwing)
const result = schema.safeParseSync(xmlString);
if (result.success) {
console.log(result.data);
} else {
console.error(result.issues);
}

Use the converter when:

  • You know the XML structure ahead of time
  • You need type safety and validation
  • You want a declarative API
  • You need to extract structured data

Use the low-level StaxXmlParser when:

  • You need maximum performance and control
  • XML structure is dynamic or unknown
  • You want event-driven processing
  • You’re building streaming applications

The x object is your entry point to the converter API. It provides factory methods for creating schemas:

  • x.string() - Parse string values
  • x.number() - Parse numeric values
  • x.object({}) - Parse structured objects
  • x.array() - Parse arrays of elements

All schemas are immutable - methods like .xpath(), .min(), .transform() return new schema instances.

Here’s a more complex example parsing an RSS feed:

const rssSchema = x.object({
title: x.string().xpath('/rss/channel/title'),
items: x.array(
x.object({
title: x.string().xpath('./title'),
link: x.string().xpath('./link'),
pubDate: x.string().xpath('./pubDate')
}),
'//item'
)
});
type RSS = Infer<typeof rssSchema>;
const rss = rssSchema.parseSync(rssXml);
console.log(`Feed: ${rss.title}`);
rss.items.forEach(item => {
console.log(`- ${item.title}: ${item.link}`);
});

The converter makes XML parsing simple, type-safe, and maintainable!