XML refuses to die, and honestly it shouldn't. It's still the backbone of plenty of real systems: Maven POMs, Android layouts, SVG, RSS feeds, SOAP services, half the enterprise integration world. And at some point you'll be handed a blob of it that looks like someone deleted every newline on purpose. Formatting that mess back into something readable is a small task you'll do hundreds of times over a career, so it's worth doing it right.
What "formatting" XML actually means
Formatting (or pretty-printing) XML is purely cosmetic. You're adding indentation and line breaks so the nesting structure is visible to a human. The parsed document is identical before and after — same elements, same attributes, same values. A machine doesn't care whether your <item> tags sit on one line or a hundred. You do.
There's a related operation, minifying, which strips the whitespace back out to shrink payload size. Both are the same idea from opposite directions, and both only touch the whitespace between nodes — never text that matters.
When you'll reach for it
- Debugging API responses. SOAP and other XML APIs love to return everything on a single 40KB line. Formatting it is the fastest way to find the one field that's wrong.
- Diffing config. A well-formatted file produces clean, line-by-line git diffs. One giant line means every change looks like the whole file changed.
- Writing or editing by hand. Nested config is painful to edit when the indentation is random.
- Code review and documentation. Pasting a readable snippet into a PR is just good manners.
Common gotchas
Whitespace inside elements is significant
This is the big one. By default XML treats whitespace between elements as insignificant, so a formatter can safely add newlines there. But text content is different. Consider:
<note>Call me <b>before</b> noon</note>
If a naive formatter reindents that into multiple lines, you can introduce spaces around <b> that weren't there. For mixed content like this, reformatting can change what the text renders as. The xml:space="preserve" attribute exists precisely to tell processors "hands off the whitespace here" — respect it, and be cautious with any element that mixes text and child tags.
CDATA sections
Anything inside <![CDATA[ ... ]]> is raw. A good formatter leaves it completely untouched. Watch out for tools that try to indent the contents — that silently corrupts embedded scripts, SQL, or HTML.
Encoding and the declaration
If the document declares <?xml version="1.0" encoding="UTF-8"?>, make sure whatever you use actually reads it as UTF-8. Mangled accented characters or smart quotes usually mean an encoding mismatch, not a formatting bug.
Comments and processing instructions
Comments (<!-- -->) and PIs should survive formatting. Some quick-and-dirty regex-based "formatters" strip or mis-indent them. Use something that parses the document properly rather than guessing at angle brackets.
It won't fix broken XML
A formatter is not a validator in disguise, but a proper one will choke on malformed input — unclosed tags, mismatched names, an ampersand that should've been &. That's actually useful: if formatting fails, your XML isn't well-formed, and you've found a bug before it hit production.
A worked example
Here's the kind of thing you get back from an API, all on one line:
<order id="1042"><customer>Ada Lovelace</customer><items><item sku="A1" qty="2">Cable</item><item sku="B7" qty="1">Adapter</item></items><total currency="GBP">19.99</total></order>
Technically valid, completely unreadable. Formatted with two-space indentation it becomes:
<order id="1042">
<customer>Ada Lovelace</customer>
<items>
<item sku="A1" qty="2">Cable</item>
<item sku="B7" qty="1">Adapter</item>
</items>
<total currency="GBP">19.99</total>
</order>
Now the structure is obvious: an order with a customer, two line items, and a total. You can scan it in a second, and if the total is wrong you know exactly where to look.
Doing it in code vs. doing it quickly
When you need formatting as part of a pipeline, use your language's real parser. In Python, for instance:
import xml.dom.minidom
raw = '<order id="1042"><customer>Ada</customer></order>'
print(xml.dom.minidom.parseString(raw).toprettyxml(indent=" "))
That works, though minidom has a well-known quirk of adding extra blank lines around existing text nodes, so you may need to clean up afterwards. In Java there's Transformer with the indent property set; in Node, libraries like fast-xml-parser handle it. Each has its own edge cases around whitespace, so test with mixed content before you trust it.
For the everyday case — you've got a messy response in your clipboard and just want to read it — scripting it is overkill. That's when I paste it into an XML Formatter and move on. No install, no dependency juggling, and it handles the CDATA and comment cases for you.
A few habits worth keeping
- Pick an indentation style (two spaces is common for XML) and stay consistent across a project.
- Commit config files pre-formatted so diffs stay meaningful.
- If formatting fails, treat it as a validity warning rather than a tooling annoyance.
- Never reformat a file where whitespace is load-bearing without checking — SVG and some data formats can be sensitive.
Formatting XML is a tiny skill, but getting the gotchas right saves you from the far worse job of debugging a payload that "looks fine" and isn't. Parse properly, respect whitespace rules, and keep a fast tool handy for the throwaway cases.
Photo by Florian Olivo on Unsplash