💻 Coding

XML Formatter

Paste XML to validate and pretty-print it instantly, with proper indentation and clear parse-error reporting.



    
0 B
Original Size
0 B
Formatted Size

About the XML Formatter

Parsing happens through the browser's built-in DOMParser, and the result gets walked by a hand-rolled recursive serializer that adds two-space indentation per nesting level, self-closes empty elements as <tag/>, and escapes &, <, and > wherever they show up in text or attribute values. If your XML is malformed, you'll see the parser's own error text rather than a vague failure message.

Why this formatter uses a real parser instead of a hand-rolled tokenizer

Several other formatters on this site, for HTML, SQL, and JavaScript, use hand-written character-by-character tokenizers rather than a full parser. XML is different: unlike HTML, which is deliberately designed to tolerate sloppy, "tag soup" markup with implicit closing tags and forgiving error recovery, XML's grammar is strict by design, every element must be explicitly closed, nesting must be well-formed, and there's no tolerance for ambiguity. That strictness is exactly what makes the browser's built-in DOMParser both available and genuinely the right tool for the job here, XML's rigid, unambiguous grammar is precisely what a real spec-compliant parser is built to enforce, so there's no need to reimplement that logic by hand the way the more permissive HTML tools on this site do.

A real DOMParser quirk: it never throws, even on invalid XML

DOMParser.parseFromString() doesn't raise a JavaScript exception when given malformed XML, it always returns a Document object no matter what. When parsing fails, the browser instead embeds a special <parsererror> element directly inside that returned document, describing what went wrong. That's exactly why this tool's error detection specifically searches for that element with doc.querySelector("parsererror") rather than wrapping the parse call in a try/catch block, a try/catch here would never actually catch anything, since DOMParser's failure mode is a special document, not a thrown error, a genuinely easy detail to miss if you haven't worked with this API before.

Why some elements collapse to one line and others spread across several

The serializer treats three cases differently on purpose. A genuinely empty element (no children at all) becomes a compact self-closing tag. An element containing only text, no nested elements, stays on a single line as <tag>value</tag>, since wrapping a simple text value across three separate lines would waste space without adding any real readability. Only elements that actually contain nested child elements (or a mix of text and elements) expand into a full multi-line indented block. This mirrors how most hand-formatted XML is conventionally written, compact where the content is simple, expanded only where there's genuine hierarchical structure worth visually representing.

An honest limitation: CDATA sections don't survive formatting as CDATA

A CDATA section (<![CDATA[...]]>) exists specifically to let XML content include characters like <, >, and & literally, without needing to escape them, useful for embedding things like snippets of HTML or code inside an XML document. This formatter treats CDATA node content the same way it treats ordinary text nodes for extraction purposes, then runs it through the same escaping logic as everything else. The resulting output is still valid, semantically identical XML, the escaped entities represent exactly the same character data the original CDATA block did, but the original CDATA wrapper syntax itself doesn't survive the round trip, it comes back out as conventionally escaped text instead of being re-wrapped in a fresh CDATA section.

Why byte-size stats matter for XML specifically

XML has a well-earned reputation for being verbose compared to formats like JSON, opening and closing tags repeat every element's full name, and attribute syntax adds further overhead per element. The Original Size and Formatted Size stats here are measured with Blob rather than plain string length, correctly counting actual UTF-8 bytes rather than JavaScript character counts, which matters if your XML contains non-ASCII content in element text or attribute values, exactly the same accurate byte-measurement approach the site's other formatter and minifier tools use for consistency.

Frequently Asked Questions

Why does this tool use the browser's DOMParser instead of a hand-written parser like the HTML formatter?

XML's grammar is strict and unambiguous by design, unlike HTML, which deliberately tolerates sloppy markup. That strictness is exactly what a spec-compliant parser like DOMParser is built to enforce, so there's no need to reimplement that logic by hand the way the site's more permissive HTML formatter does.

Does DOMParser throw an error when given invalid XML?

No, it never throws a JavaScript exception, it always returns a Document object. On failure, it embeds a special parsererror element inside that document describing the problem, which is why this tool searches for that element rather than using a try/catch block.

Why do some elements stay on one line while others span multiple lines?

An element with only text content (no nested elements) stays compact on one line, since spreading a simple value across three lines wastes space. Only elements containing actual nested child elements expand into a full indented block, matching how XML is typically hand-formatted.

Will my CDATA sections stay as CDATA after formatting?

No, CDATA content is extracted and escaped the same way as ordinary text, producing valid, semantically identical XML, but the original CDATA wrapper syntax doesn't survive, it comes back as conventionally escaped text instead of being re-wrapped in a CDATA section.

Are XML comments and processing instructions preserved?

Yes, both are detected as distinct node types during parsing and included in the formatted output in their original position, comments as <!-- --> blocks and processing instructions like <?xml-stylesheet ?> preserved with their original target and data.

What happens to characters like & and < inside attribute values?

They're automatically escaped into their entity equivalents (&amp;, &lt;, and so on), along with quotes inside attribute values specifically, ensuring the formatted output remains valid XML regardless of what characters your original content contained.