# @rgrove/parse-xml

> A fast, safe, compliant XML parser for Node.js and browsers.

Latest version **5.0.0** (published 2026-08-30) · ISC license · 0 weekly downloads

## Install

```sh
npm install @rgrove/parse-xml
pnpm add @rgrove/parse-xml
yarn add @rgrove/parse-xml
bun add @rgrove/parse-xml
```

## Health

**Score 70/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; recently updated; high maintenance score; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 5.0.0 |
| Published | 2026-08-30 |
| First published | 2017-06-04 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=22.12.0 |
| Dependencies | 0 |
| Unpacked size | 207 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 320 |
| Author | Ryan Grove |
| Maintainers | rgrove |
| Keywords | xml, xml parser, parse-xml, parse xml, parse, parser |

## Links

- npm: https://www.npmjs.com/package/@rgrove/parse-xml
- Repository: https://github.com/rgrove/parse-xml
- Issues: https://github.com/rgrove/parse-xml/issues
- npm.io page: https://npm.io/package/@rgrove/parse-xml

## Alternatives

- [babylon](https://npm.io/package/babylon.md) — 5.1M weekly downloads
- [csscolorparser](https://npm.io/package/csscolorparser.md) — 3.7M weekly downloads
- [expr-eval-fork](https://npm.io/package/expr-eval-fork.md) — 1.5M weekly downloads
- [@leeoniya/ufuzzy](https://npm.io/package/@leeoniya/ufuzzy.md) — 247.7K weekly downloads
- [xml-parser](https://npm.io/package/xml-parser.md) — 78.4K weekly downloads

## Recent versions

- 5.0.0 (latest) — 2026-08-30
- 4.2.3 — 2026-07-26
- 4.2.2 — 2026-07-11
- 4.2.1 — 2026-06-27
- 4.2.0 — 2024-10-25
- 4.1.0 — 2023-02-05
- 4.0.1 — 2022-10-17
- 4.0.0 — 2022-09-26
- 3.0.0 — 2021-01-23
- 2.0.4 — 2020-05-02
- 2.0.3 — 2020-04-20
- 2.0.2 — 2020-01-10
- 2.0.1 — 2019-04-10
- 2.0.0 — 2019-01-20
- 2.0.0-next.0 — 2019-01-01
- … 3 more at https://npm.io/package/@rgrove/parse-xml/versions

## README

# parse-xml

A fast, safe, compliant XML parser for Node.js and browsers.

[![npm version](https://img.shields.io/npm/v/%40rgrove%2Fparse-xml)](https://npmx.dev/package/@rgrove/parse-xml) [![Bundle size](https://badgen.net/bundlephobia/minzip/@rgrove/parse-xml)](https://bundlephobia.com/result?p=@rgrove/parse-xml) [![CI](https://github.com/rgrove/parse-xml/actions/workflows/ci.yml/badge.svg)](https://github.com/rgrove/parse-xml/actions/workflows/ci.yml)

## Links

- [API Docs](https://rgrove.github.io/parse-xml/)
- [GitHub](https://github.com/rgrove/parse-xml)
- [npmx](https://npmx.dev/package/@rgrove/parse-xml)

## Installation

```
npm install @rgrove/parse-xml
```

Or, if you like living dangerously, you can load [the minified bundle](https://unpkg.com/@rgrove/parse-xml/dist/global.min.js) in a browser via [Unpkg](https://unpkg.com/) and use the `parseXml` global.

## Features

-   Returns a convenient [object tree](#basic-usage) representing an XML document.

-   Works great in Node.js and browsers.

-   Provides [helpful, detailed error messages](#friendly-errors) with context when a document is not well-formed.

-   Mostly conforms to [XML 1.0 (Fifth Edition)](https://www.w3.org/TR/2008/REC-xml-20081126/) as a non-validating parser (see [below](#not-features) for details).

-   Passes all relevant tests in the [XML Conformance Test Suite](https://www.w3.org/XML/Test/).

-   Written in TypeScript and compiled to ES2020 JavaScript for Node.js and ES2017 JavaScript for browsers. The browser build is also optimized for minification.

-   Extremely [fast](#benchmark) and surprisingly [small](https://bundlephobia.com/result?p=@rgrove/parse-xml).

-   Zero dependencies.

## Not Features

While this parser is capable of parsing document type declarations (`<!DOCTYPE ... >`) and including them in the node tree, it doesn't actually do anything with them. External document type definitions won't be loaded, and the parser won't validate the document against a DTD or resolve custom entity references defined in a DTD.

In addition, the only supported character encoding is UTF-8 because it's not feasible (or useful) to support other character encodings in JavaScript.

## Examples

### Basic Usage

```js
import { parseXml } from '@rgrove/parse-xml';
parseXml('<kittens fuzzy="yes">I like fuzzy kittens.</kittens>');
```

The result is an [`XmlDocument`](https://rgrove.github.io/parse-xml/classes/XmlDocument.html) instance containing the parsed document, with a structure that looks like this (some properties and methods are excluded for clarity; see the [API docs](https://rgrove.github.io/parse-xml/) for details):

```js
{
  type: 'document',
  children: [
    {
      type: 'element',
      name: 'kittens',
      attributes: {
        fuzzy: 'yes'
      },
      children: [
        {
          type: 'text',
          text: 'I like fuzzy kittens.'
        }
      ],
      parent: { ... },
      isRootNode: true
    }
  ]
}
```

All parse-xml objects have `toJSON()` methods that return JSON-serializable objects, so you can easily convert an XML document to JSON:

```js
let json = JSON.stringify(parseXml(xml));
```

### Friendly Errors

When something goes wrong, parse-xml throws an error that tells you exactly what happened and shows you where the problem is so you can fix it.

```js
parseXml('<foo><bar>baz</foo>');
```

**Output**

```
Error: Missing end tag for element bar (line 1, column 14)
  <foo><bar>baz</foo>
               ^
```

In addition to a helpful message, error objects have the following properties:

-   **column** _Number_

    Column where the error occurred (1-based).

-   **excerpt** _String_

    Excerpt from the input string that contains the problem.

-   **line** _Number_

    Line where the error occurred (1-based).

-   **pos** _Number_

    Character position where the error occurred relative to the beginning of the input (0-based).

## Why another XML parser?

There are many XML parsers for Node, and some of them are good. However, most of them suffer from one or more of the following shortcomings:

-   Native dependencies.

-   Loose, non-standard parsing behavior that can lead to unexpected or even unsafe results when given input the author didn't anticipate.

-   Kitchen sink APIs that tightly couple a parser with DOM manipulation functions, a stringifier, or other tooling that isn't directly related to parsing and consuming XML.

-   Stream-based parsing. This is great in the rare case that you need to parse truly enormous documents, but can be a pain to work with when all you want is a node tree.

-   Poor error handling.

-   Too big or too Node-specific to work well in browsers.

parse-xml's goal is to be a small, fast, safe, compliant, non-streaming, non-validating, browser-friendly parser, because I think this is an under-served niche.

I think parse-xml demonstrates that it's not necessary to jettison the spec entirely or to write complex code in order to implement a small, fast XML parser.

Also, it was fun.

## Benchmark

Here's how parse-xml's performance stacks up against a few comparable libraries:

-   [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser), which claims to be the fastest pure JavaScript XML parser
-   [libxmljs2](https://github.com/marudor/libxmljs2), which is based on the native libxml library written in C
-   [xmldoc](https://github.com/nfarina/xmldoc), which is based on [sax-js](https://github.com/isaacs/sax-js)

While libxmljs2 is faster at parsing medium and large documents, its performance comes at the expense of a large C dependency, no browser support, and a [history of security vulnerabilities](https://www.cvedetails.com/vulnerability-list/vendor_id-1962/product_id-3311/Xmlsoft-Libxml2.html) in the underlying libxml2 library.

In these results, "ops/s" refers to operations per second. Higher is faster.

```
Node.js v24.20.0 / Darwin arm64
Apple M1 Max

Running "Small document (291 bytes)" suite...
Progress: 100%

  @rgrove/parse-xml 5.0.0:
    210 841 ops/s, ±0.08%   | fastest

  fast-xml-parser 5.11.1:
    106 088 ops/s, ±0.11%   | 49.68% slower

  libxmljs2 0.37.0 (native):
    76 733 ops/s, ±2.35%    | slowest, 63.61% slower

  xmldoc 3.0.0 (sax-js):
    141 395 ops/s, ±0.12%   | 32.94% slower

Finished 4 cases!
  Fastest: @rgrove/parse-xml 5.0.0
  Slowest: libxmljs2 0.37.0 (native)

Running "Medium document (72081 bytes)" suite...
Progress: 100%

  @rgrove/parse-xml 5.0.0:
    1 208 ops/s, ±0.15%   | 51.68% slower

  fast-xml-parser 5.11.1:
    466 ops/s, ±0.10%     | slowest, 81.36% slower

  libxmljs2 0.37.0 (native):
    2 500 ops/s, ±3.03%   | fastest

  xmldoc 3.0.0 (sax-js):
    914 ops/s, ±0.41%     | 63.44% slower

Finished 4 cases!
  Fastest: libxmljs2 0.37.0 (native)
  Slowest: fast-xml-parser 5.11.1

Running "Large document (1162464 bytes)" suite...
Progress: 100%

  @rgrove/parse-xml 5.0.0:
    110 ops/s, ±0.08%   | 54.36% slower

  fast-xml-parser 5.11.1:
    40 ops/s, ±0.35%    | slowest, 83.4% slower

  libxmljs2 0.37.0 (native):
    241 ops/s, ±3.28%   | fastest

  xmldoc 3.0.0 (sax-js):
    84 ops/s, ±0.12%    | 65.15% slower

Finished 4 cases!
  Fastest: libxmljs2 0.37.0 (native)
  Slowest: fast-xml-parser 5.11.1
```

See the [parse-xml-benchmark](https://github.com/rgrove/parse-xml-benchmark) repo for instructions on how to run this benchmark yourself.

## License

[ISC License](LICENSE)

---
_Source: https://npm.io/package/@rgrove/parse-xml · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
