Convert XML into lightweight, queryable JavaScript objects without a DOM.
Install xml2o with your package manager:
npm install xml2obun add xml2oyarn add xml2oconvertString and convertStream parse asynchronously and return a
Promise<Node>.
import { convertString } from "xml2o";
const root = await convertString('<root><item id="1">value</item></root>');
console.log(root.query("item")[0]?.text); // valueconst { convertString } = require("xml2o");
async function readXml() {
const root = await convertString('<root><item id="1">value</item></root>');
console.log(root.query("item")[0]?.getAttribute("id")); // 1
}
readXml();Pass a Node.js readable stream to convertStream:
import { createReadStream } from "node:fs";
import { convertStream } from "xml2o";
const root = await convertStream(createReadStream("/path/to/file.xml"));Invalid XML rejects the returned promise, so handle conversion errors with
try/catch or .catch():
try {
await convertString("<root><item></root>");
} catch (error) {
console.error("Could not parse XML", error);
}Parses an XML string and resolves to the root Node.
Parses a readable stream and resolves to the root Node.
A Node is an array of its child nodes. It exposes the element's name,
local name, prefix, namespace uri, parent, and root. Its text
property concatenates text and CDATA received for the node and its direct child
elements.
Use attribute helpers to read attributes:
const item = root.query("item")[0];
item?.getAttribute("id"); // "1"
item?.hasAttribute("id"); // true
item?.getAttributeNode("id"); // Attribute | undefined
item?.getAttributes(); // { id: "1" }getAttribute, getAttributeNode, and hasAttribute accept an optional
namespace URI as their second argument. getAttributes(uri) returns attributes
in that namespace; without an argument it returns non-namespaced attributes.
Use query(path, uri?) to find child elements by their local name. Paths have
these forms:
| Path | Meaning |
|---|---|
"item" |
Find every descendant item node. |
"group/item" |
Find an item below a matching group at any depth. |
"/group/item" |
Follow the path from the current node. |
"/" |
Return the current node. |
Pass a namespace URI as the second argument to restrict matches:
const namespacedItems = root.query("item", "urn:example");
const code = namespacedItems[0]?.getAttribute("code", "urn:example");An Attribute exposes its name, local name, prefix, namespace uri, and
string value. Calling attribute.toString() returns its value.
This project uses Bun for development:
bun install
bun run security
bun test
bun run build
bun run checkMIT