Lightweight XML to JSON parser with zero dependencies. Works in browser, Node.js, and Deno.
Designed for parsing XML APIs (WebDAV PROPFIND, S3 ListBucket, etc.) in environments where DOMParser is unavailable — such as service workers.
import { parseXml } from "@violentmonkey/xml-parser";
const { node, warnings } = parseXml(`<?xml version="1.0"?>
<D:multistatus xmlns:D="DAV:">
<D:response>
<D:href>/file.txt</D:href>
<D:propstat>
<D:prop>
<D:displayname>file.txt</D:displayname>
<D:getcontentlength>1234</D:getcontentlength>
</D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response>
</D:multistatus>`);
// node.multistatus.response.href → "/file.txt"
// node.multistatus.response.propstat.prop.displayname → "file.txt"
// node.multistatus.response.propstat.prop.getcontentlength → 1234 (number)Parameters:
input(string) — XML text to parse.options(optional):ignoreAttributes(boolean) — Skip all attributes. Defaultfalse.removeNSPrefix(boolean) — Strip namespace prefixes from element names. Defaulttrue.
Returns: { node: Record<string, XmlValue>, warnings: Warning[] }
type XmlValue = string | number | { [key: string]: XmlValue } | XmlValue[];| Feature | Description |
|---|---|
| Namespace handling | Strips D: → D:response becomes response by default. Opt out with removeNSPrefix: false. |
| Attributes | Prefixed with @, e.g. <item id="42"> → { "@id": "42" }. xmlns* attributes are skipped. |
| Text vs object | Text-only elements return string/number; elements with children return object. |
| Arrays | Repeated sibling elements are automatically wrapped in an array. |
| Numbers | Numeric strings like "1234" are parsed as numbers. |
| CDATA | CDATA sections are treated as text content. |
| Warnings | Non-fatal issues (e.g. duplicate attributes) are returned in warnings array. |
| Zero dependencies | ~250 lines of pure TypeScript. |
MIT