XML Formatter

Format, minify, and validate XML — copy and paste the result.

This free online XML formatter pretty-prints or minifies XML, with adjustable indentation. Comments, CDATA sections, and the XML declaration are preserved exactly. Invalid XML shows a clear parser error instead of a broken result. No signup required, runs entirely in your browser.

Examples:

Mode

Indent

Preserved as-is

<?xml version="1.0"?>
XML declaration
<!-- comment -->
Comments
<![CDATA[ ... ]]>
CDATA sections
XML Input
Valid XML

Frequently asked questions

Paste your XML into the input above with the mode set to Format. The tool validates it and pretty-prints it with your chosen indentation (2 spaces, 4 spaces, or a tab). Invalid XML shows a clear parser error instead of a broken result.
Switch the mode to Minify. The tool removes all insignificant whitespace between tags and outputs the XML as compactly as possible — useful for reducing payload size before sending it over the network.
Yes. Every format or minify pass first parses the XML with your browser's built-in XML parser. If the document isn't well-formed — a mismatched tag, an unclosed element, invalid characters — the parser's error message is shown instead of a result.
Yes. Comments, CDATA sections, and the XML declaration (<?xml version="1.0"?>) are all kept exactly as written — only whitespace between tags is added or removed depending on the mode.
No. Everything is parsed and formatted locally in your browser using the native XML parser. Nothing is uploaded or stored on a server.
' }, { label: 'Invalid (mismatched tags)', value: '' }, ], get _result() { const text = this.input; if (!text.trim()) return { ok: true, value: '' }; try { if (this.mode === 'minify') { return { ok: true, value: minifyXml(text) }; } const space = this.indent === 'tab' ? '\t' : ' '.repeat(Number(this.indent)); return { ok: true, value: formatXml(text, space) }; } catch (e) { return { ok: false, value: '', error: e.message }; } }, get output() { return this._result.value; }, get parseError() { return this._result.ok ? null : this._result.error; }, loadExample(ex) { this.input = ex.value; }, clearInput() { this.input = ''; }, async copyOutput() { const text = this.output; if (!text) return; try { await navigator.clipboard.writeText(text); } catch { const el = document.createElement('textarea'); el.value = text; document.body.appendChild(el); el.select(); document.execCommand('copy'); document.body.removeChild(el); } this.copied = true; setTimeout(() => { this.copied = false; }, 2000); }, })); if (window.Alpine) { register(); } else { document.addEventListener('alpine:init', register); } })();