dev101.io

XML Formatter

Format, validate, and pretty-print XML in your browser — privately.

Loading tool…

How to use XML Formatter

  1. Paste XML into the input panel on the left.
  2. Pick your indent (2 spaces, 4 spaces, or a tab).
  3. Toggle `Minify` to emit a single-line document without any insignificant whitespace.
  4. Toggle `Collapse empty` to rewrite empty elements as self-closing.
  5. Pick a `Declaration` policy — Preserve keeps an existing `<?xml … ?>`, Add inserts one if absent, Strip removes it.
  6. Press the Format button (or ⌘/Ctrl + Enter) to pretty-print. The output panel updates with your formatted XML.
  7. Use Copy output to grab the result, or Share to generate a URL that restores your session.

XML Formatter

A keyboard-driven XML formatter, validator, and pretty-printer that runs entirely in your browser. Paste raw XML, get a clean, indented, well-formed document back. Minify on demand for a single-line payload. Toggle self-closing empty elements. Everything happens on your device — no network request, no server log.

Why another XML formatter?

Most online XML formatters do the work on a server. That's fine for toy documents, but nearly every real-world XML file is a config, a protocol payload, or a data export — a SOAP envelope, an Android layout, an SVG icon, an RSS feed, a CloudFormation template, a Maven POM, a sitemap. Those files routinely contain internal hostnames, IAM ARNs, auth tokens, XPath-laden comments, and structured data that nobody wants sitting in a third-party server log.

This tool ships a tiny hand-rolled XML tokenizer and pretty-printer as a client-side transform straight into the page. The parser is written in plain TypeScript with no dependencies — fewer than a thousand lines of code — and it runs in the same process that holds your textarea. No network call, no server log, no telemetry. Your XML stays on your machine.

What it does

  • Format: parse, then re-emit with your chosen indent (2, 4, or tab). Element-only parents get each child on its own line; mixed content (text siblings adjacent to elements) is kept inline to preserve meaning.
  • Validate: every keystroke re-parses the input and flips a badge to Valid XML or Invalid. On failure, the error banner shows the exact line and column.
  • Minify: collapse a multi-line document to a single line, dropping every byte of insignificant whitespace while keeping the document well-formed.
  • Collapse empty: rewrite <x></x> as <x/> — two bytes shorter, same meaning.
  • Declaration control: preserve, add, or strip the <?xml … ?> prolog.
  • Preserves: attribute order, namespace prefixes (xmlns:foo), comments, CDATA, processing instructions, DOCTYPE, XML declaration, entity references (verbatim), self-closing tags.

Examples

Pretty-print this:

<a><b><c>hi</c></b></a>

into this:

<a>
  <b>
    <c>
      hi
    </c>
  </b>
</a>

Minify it back to a single line when you need to paste it into a protocol payload or a URL parameter.

Mixed content is kept inline — the formatter knows the difference between "element-only" structure and "prose with inline markup":

<p>hello <b>bold</b> world</p>

stays exactly like that instead of being expanded to put every word on its own line.

What's preserved, what isn't

Preserved: element structure, attribute order, namespace prefixes, comments, CDATA sections, processing instructions, the XML declaration, DOCTYPE (including internal subsets with [ … ]), entity references (verbatim — &amp; stays as &amp;).

Normalized: attribute quote style (all double quotes on output), empty-element form (controlled by Collapse empty), insignificant whitespace between element siblings (dropped).

Rejected: malformed input. Unclosed tags, mismatched close tags, duplicate attributes, unterminated attribute values, and other well-formedness violations surface as structured errors with 1-based line/column so you can jump to the problem.

Privacy and performance

There is no analytics, no telemetry, no third-party script that touches your input. The Share button encodes a base64url snapshot of your input and settings into the URL fragment (#s=…), which by HTTP design is never sent to any server. Sharing a link is a peer-to-peer transfer of state.

The parser handles multi-megabyte documents comfortably; the bottleneck is textarea rendering rather than the parse itself. For hundreds-of-megabytes streams, use a dedicated XML toolchain rather than forcing a browser textarea to render them.

Keyboard shortcuts

  • ⌘/Ctrl + Enter — Format

The shortcut works even while focus is in the input textarea, because it includes a modifier key.

Related tools

Frequently asked questions

Is the XML I paste sent to your servers?

No. Every transformation runs locally in your browser using a tiny hand-rolled XML tokenizer and tree printer bundled into the page. There is no XML-handling endpoint on dev101.io — we deliberately avoid round-trips so your SOAP envelopes, SVG markup, RSS feeds, Android layouts, configuration files, and sitemaps — which routinely contain internal hostnames, auth tokens, API keys, and comments you don't want indexed — never leave your device. The Share button encodes state into the URL hash, which by HTTP design is never transmitted to any server.

What does "Collapse empty" do?

An empty element written as `<x></x>` is semantically identical to the self-closing form `<x/>`. With `Collapse empty` on (the default), the formatter rewrites the long form into the short one, saving three bytes per occurrence. Turn it off when a downstream consumer insists on seeing a matched open-and-close pair for empty elements — some legacy SOAP stacks still do.

Are comments, CDATA, and processing instructions preserved?

Yes. The parser emits a typed node tree that distinguishes elements, text, comments (`<!-- … -->`), CDATA sections (`<![CDATA[ … ]]>`), processing instructions (`<?foo … ?>`), the XML declaration (`<?xml … ?>`), and the DOCTYPE. All of these round-trip from input to formatted output — only insignificant whitespace between element siblings is dropped.

What happens to entity references like `&amp;` and `&#x20;`?

They are preserved verbatim. The formatter does not resolve or re-encode character and named entity references — if you type `&amp;`, the output contains `&amp;`; if you type a bare `&` followed by text that is not a valid reference, the output escapes it to `&amp;` so the result is well-formed. This keeps the formatter losslessly round-trippable for inputs that already use entity references correctly.

Is attribute order preserved?

Yes. Attributes are emitted in source order. Attribute quote style is normalized to double quotes for consistency; embedded double quotes inside attribute values are escaped to `&quot;`. Single-quoted input attributes are re-emitted with double quotes.

What error detail do I get for malformed input?

The parser surfaces a 1-based line and column number for every failure — unclosed tags, mismatched close tags, unterminated attribute values, CDATA at the top level, duplicate attributes, and so on. The error banner shows the exact position so you can jump to the offending character.

Related tools