You pasted XML into a file that one tool reads fine and another rejects, or you inherited a 4-megagram one-liner someone's build spat out. Formatting fixes the readability; validation tells you whether the readability is even deserved. Here are the seven rules a document must obey, the five entities everyone Googles, and a real byte-for-byte example of what minification actually buys.
Real formatting is parse, then re-serialize — not search-and-replace on angle brackets. The formatter reads your document into a tree, checks it against XML's syntax rules, and writes the tree back out with a consistent layout: one element per line, each nesting level indented one stop, text kept inline with its parent. Because the output comes from the parsed tree, the structure can't drift; a formatter that hasn't parsed the document can corrupt it.
That's also why a good formatter doubles as a validator: if parsing fails, you learn immediately — ideally with a line and column — instead of after the document has been through three more systems.
| # | Rule | Breaks like this |
|---|---|---|
| 1 | Exactly one root element | <a/><b/> at the top level |
| 2 | Every tag closed | <a><b></a> |
| 3 | Nesting closes in reverse order | <a><b></a></b> |
| 4 | Names are case-sensitive | <item></Item> doesn't match |
| 5 | Attribute values quoted | <a id=1> |
| 6 | < and & escaped in content | <name>A & B</name> |
| 7 | Declaration first, if present | any byte before <?xml …?> |
A document that passes all seven is well-formed. A document that additionally obeys a DTD or XSD schema is valid — a stronger claim, and one that needs the schema itself. When a tool says "XML validator," check which of the two it means; most online ones, including ours, check well-formedness.
Five characters have predefined escapes: < for <, > for >, & for &, " for ", and ' for '. Strictly only < and & must be escaped in character content — the other three matter inside attribute values delimited by the same quote — but escaping all five everywhere is always safe, which is what most serializers do. For blocks of raw code or math, a CDATA section (<![CDATA[ 1 < 2 ]]>) skips escaping entirely; note the one thing CDATA still can't contain is the sequence ]]>.
Take a two-entry feed document, pretty-printed at 2-space indentation: 563 bytes over 20 lines. Minified — every newline and indent removed — the same document runs 477 bytes. That's a 15.3% reduction for deleting nothing but whitespace, and round-tripping proves it: formatting the minified version reproduces the original line-for-line, 563 bytes in, 562 out, with only the trailing newline lost.
The parse also yields structure stats that matter more than size when you're auditing a document: this feed has 14 elements, 9 attributes, and a maximum nesting depth of 4. Depth is the one to watch — deeply nested XML is where humans miscount close tags, and depth above 6 or 7 usually means the format wants refactoring, not reformatting.
How much minification saves scales with how padded the source was: this feed carries modest 2-space indents; machine-generated XML indented to 8 spaces at depth 8 can halve. Already-dense XML barely moves.
Usually, no. XML gzips exceptionally well — closing tags are repetitive, exactly what DEFLATE eats — so the transport layer generally shrinks documents better than minification does, and minified payloads are miserable to debug. Minification earns its keep for very large documents served without compression, or high-volume machine-to-machine feeds where every byte bills twice. Whatever ships, keep the pretty version in source control; the XML formatter converts either direction in one click.
People repeat "JSON is smaller," and it's not that simple. JSON repeats every key for every record; XML can carry the same facts as attributes with short names. On the feed example above, minified XML is 477 bytes while the equivalent compact JSON is 755 bytes — 37% larger. Flip to a document of nested containers with few attributes and JSON wins. The honest rule: measure on your payload, and remember JSON has no attributes, namespaces, mixed content, or a standard schema system — which is usually the actual reason to pick one over the other, not bytes.
xmllint --format file.xml everywhere; Python's xml.dom.minidom one-liner when you need it scripted.For sibling formats, the JSON formatter and YAML validator do the same parse-and-reprint job for their grammars, and the SQL formatter handles the query side of configs.
Paste XML, pick 2-space or 4-space indentation, and get structure stats plus exact error positions. Runs entirely in your browser.
XML Formatter →Formatting is re-serialization: parse the document, print the tree consistently, and any parse failure is a syntax bug with an address — line and column. Obey the seven rules, escape the five entities, minify only when bandwidth genuinely bills you for it, and keep the pretty version under version control. The XML formatter does all three modes in one paste, the JSON formatter covers the other half of config work, and the YAML validator tames the third format your pipeline secretly contains.
Parsing reads the text and builds a tree, failing if the syntax is broken. Formatting re-serializes that tree with consistent layout — one element per line, children indented. A real formatter always parses first, which is why formatting a broken document should report an error instead of producing garbage.
Rarely worth it. XML compresses extremely well with gzip or brotli — the transport layer usually handles size — and minified files are miserable to debug by hand. Minification pays off for very large documents shipped uncompressed, or for machine-to-machine payloads where a 15-40% byte reduction matters to bandwidth bills. Keep pretty files in the repo either way.
Unescaped < and & in content, and most control characters below 0x20 (only tab, newline, and carriage return are allowed). Escape the five entity characters — < > & " ' — and reject or wrap control characters in CDATA where legal. Invalid Unicode bytes fail at parse time regardless of formatting.
The declaration, if present, must be the very first thing in the file with no leading whitespace or blank line, or the parser rejects it. Comments can live anywhere after it and survive formatting untouched. A formatter that indents or moves the declaration is broken.
xmllint --format file.xml is the classic one-liner on macOS and Linux. Python's xml.dom.minidom parses and reprints in a one-liner too. For quick one-off files, the browser-based ToolAspect XML formatter does the same with nothing to install.