XML parser and stringifier with a JSON-compatible API.
- Familiar API - Same
parse/stringifyinterface as JSON - Typed - Full TypeScript support included
- Namespace support - Handle XML namespaces with ease
- CDATA support - Preserve raw CDATA sections
- Formatting - Pretty-print with custom indentation
- Reviver/Replacer - Transform data during parsing and stringifying
import XML from "@liquiddev/xml";
// Parse XML to object
const obj = XML.parse("<foo>bar</foo>");
// { foo: "bar" }
// Stringify object to XML
const xml = XML.stringify({ foo: "bar" });
// "<foo>bar</foo>"If you know JSON, you know this library:
| JSON | XML |
|---|---|
JSON.parse(text) |
XML.parse(text) |
JSON.stringify(value) |
XML.stringify(value) |
{ "key": "value" } |
<key>value</key> |
null |
<key/> (self-closing) |
{ "@attr": "x" } |
<key attr="x"/> |
{ "@id": "1", "#text": "x" } |
<key id="1">x</key> |
npm install @liquiddev/xmlThe API mirrors JavaScript's built-in JSON object:
import XML from "@liquiddev/xml";Parses an XML string into a JavaScript object.
const obj = XML.parse("<foo>bar</foo>");
// { foo: "bar" }Converts a JavaScript object to an XML string.
const xml = XML.stringify({ foo: "bar" });
// "<foo>bar</foo>"Element names become object keys:
XML.parse("<foo><bar>baz</bar></foo>");
// { foo: { bar: "baz" } }Attributes use the @ prefix:
XML.parse('<foo id="1"></foo>');
// { foo: { "@id": "1" } }
XML.stringify({ foo: { "@id": "1" } });
// '<foo id="1"/>'Text content when attributes present is stored as #text:
XML.parse('<foo id="1">hello</foo>');
// { foo: { "@id": "1", "#text": "hello" } }Multiple children with the same name become arrays:
XML.parse("<foo><bar/><bar/></foo>");
// { foo: { bar: [{}, {}] } }Mixed content uses the #children array to maintain ordering:
XML.parse("<foo><bar/>text</foo>");
// { foo: { "#children": [{ bar: {} }, "text"] } }CDATA sections are represented with [CDATA]:
XML.parse("<foo><![CDATA[raw text]]></foo>");
// { foo: { "[CDATA]": "raw text" } }Namespaces use the $ prefix:
XML.parse('<foo xmlns:ns="http://example.com"><ns:bar>text</ns:bar></foo>');
// { foo: { $ns: "http://example.com", "ns:bar": "text" } }
// Default namespace
XML.parse('<foo xmlns="http://example.com"><bar>text</bar></foo>');
// { foo: { $default: "http://example.com", bar: "text" } }Use XML.rawXML() to embed unescaped XML:
const obj = {
foo: XML.rawXML("<bar>raw</bar>"),
};
XML.stringify(obj);
// "<foo><bar>raw</bar></foo>"Like JSON.parse and JSON.stringify, you can pass reviver and replacer functions:
// Parse with reviver
const obj = XML.parse("<foo>123</foo>", (key, value) => {
if (key === "foo" && typeof value === "string") return Number(value);
return value;
});
// { foo: 123 }
// Stringify with replacer
const xml = XML.stringify({ foo: 123 }, (key, value) => {
if (typeof value === "number") return String(value);
return value;
});
// "<foo>123</foo>"
// Replacer array acts as a whitelist for properties to include
const xml = XML.stringify({ foo: { a: 1, b: 2 } }, ["a"]);
// "<foo><a>1</a></foo>"The space parameter adds indentation:
XML.stringify({ foo: { bar: "text" } }, null, 2);
// <foo>
// <bar>text</bar>
// </foo>
XML.stringify({ foo: { bar: "text" } }, null, "\t");
// <foo>
// <bar>text</bar>
// </foo>Types are included:
import XML, { type XMLNode, type XMLAttr } from "@liquiddev/xml";
const obj: XMLNode = XML.parse("<foo>bar</foo>");MIT