npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

o2xml

v0.3.3

Published

Convert JavaScript objects to XML

Readme

o2xml

o2xml converts a JavaScript object tree into XML. It has no runtime dependencies and provides ESM, CommonJS, and TypeScript declarations.

Install

Use the command for your package manager:

npm install o2xml
bun add o2xml
yarn add o2xml

Use

ESM:

import { transform } from "o2xml";

const xml = transform({ root: { "@id": 1, "#text": "value" } });

console.log(xml);
// <root id="1">value</root>

CommonJS:

const { transform } = require("o2xml");

const xml = transform({ root: { "@id": 1, "#text": "value" } });

console.log(xml);
// <root id="1">value</root>

The packed package exposes the same transform and TransformObject runtime exports in both module formats.

Object model

The input must have exactly one enumerable root property, and the root value cannot be an array. Plain-object keys become elements. Keys beginning with @ become attributes on that object’s element; a string-valued key beginning with # becomes a text fragment, without an enclosing element. Text fragments and elements are emitted in property order.

const xml = transform({
    div: {
        "@id": "greeting",
        "#text": "Hello, ",
        span: { "@style": "font-weight: bold", "#text": "World" },
        "#tail": "!",
    },
});

console.log(xml);
// <div id="greeting">Hello, <span style="font-weight: bold">World</span>!</div>

Children can be strings, numbers, booleans, null, plain objects, arrays, Date instances, or Node.js Buffer instances. Arrays repeat the element for each item; dates use toISOString() by default; buffers use base64. true and false become 1 and 0. Empty strings and null produce self-closing elements, and a null attribute becomes an empty string.

By default, strings and attribute strings escape ", ', &, <, and >. Element and attribute names are validated. The transformer throws for an input without exactly one root, an array root, invalid names, unsupported attribute values, and unsupported object children such as regular expressions.

Input mutation

During transformation, @ properties are consumed from plain-object nodes: they are read as attributes and removed from those input objects. Clone the object first if you need to retain those properties after calling transform.

Options and formatters

transform(object, options) accepts these options:

  • pretty — formats nested elements with newlines and indentation; default: false.
  • indent — indentation used by pretty; default: two spaces.
  • declaration — prepends <?xml version="1.0" encoding="UTF-8" ?>; default: false.
  • formatters — optional callbacks for string, number, boolean, and date values. Each callback receives the value and returns the XML text to use.
import type { AnyObject, TransformFormatter, TransformOptions } from "o2xml";

const number: TransformFormatter<number> = (value) => `n:${value}`;
const options: TransformOptions = {
    pretty: true,
    indent: "\t",
    declaration: true,
    formatters: {
        number,
        boolean: String,
        date: () => "DATE",
        string: (value) => value.toUpperCase(),
    },
};
const value: AnyObject = { root: { value: 2 } };

transform(value, options);

AnyObject describes the input shape, TransformFormatter<T> describes a formatter callback, and TransformOptions describes the optional second argument. A custom string formatter replaces the default escaping, so it must escape XML itself when needed.

Development

This repository uses Bun:

bun install
bun run security
bun test
bun run build
bun run check