Free online XML formatter. Pretty-print and indent messy XML, minify it, and check it is well-formed — instantly and privately in your browser.
Paste XML into the left pane and the formatted version appears on the right immediately. There is no upload step, no Format button to hunt for, and no account. The banner above the two panes tells you straight away whether the document is well-formed, and if it is not, it shows the parser's own error message — line number, column number and the specific complaint — so you can go fix the character that is actually wrong instead of squinting at a wall of one-line XML.
Everything runs client-side in JavaScript. The XML you paste never leaves the tab, which matters when the document you are debugging is an invoice, a SOAP envelope with credentials in the header, a SAML assertion, or an export from a system you are not supposed to be pasting into random websites. You can confirm this yourself: load the page, disconnect from the network, and the formatter keeps working.
The toggle at the top left switches between the two things people actually want from an XML tool.
<price>44.95</price> — is collapsed onto one line rather than being exploded across three, which is what makes a beautified catalogue readable instead of merely tall.Both modes preserve the parts of an XML document that naive whitespace-stripping tends to destroy: comments, <![CDATA[ ]]> sections, processing instructions, the <?xml ?> declaration and any <!DOCTYPE> line all survive intact. The tag scanner is quote-aware, so an attribute value containing a > character — <rule expr="a > b"/> — does not fool it into ending the tag early, which is a classic failure of regex-based formatters.
Minification trims the whitespace around text content as well as between tags. For the overwhelming majority of XML — configuration files, API payloads, data exports — that is exactly what you want. But if your document uses mixed content, where text and elements sit side by side inside the same parent and the spacing between them is meaningful (document-oriented XML such as DocBook, XHTML fragments, or anything with xml:space="preserve"), minifying can change what the document means. Beautify the file instead, and keep the original if whitespace is load-bearing.
Three different checks get called "XML validation" in casual conversation, and confusing them is the single biggest source of wasted debugging time.
| Check | Question it answers | Does this tool do it? |
|---|---|---|
| Formatting | Is it readable? Is it indented consistently? | Yes — Beautify and Minify |
| Well-formedness | Does it obey XML's syntax rules at all? Can any parser read it? | Yes — the banner |
| Validity | Does it match a specific DTD or XSD schema — right elements, right order, right data types? | No |
Well-formed means the document satisfies XML's universal grammar: exactly one root element, every open tag closed, tags nested rather than overlapped, attribute values quoted, reserved characters escaped. A well-formed document can still be complete nonsense for your purpose — <order><banana/></order> is perfectly well-formed and will be rejected instantly by any order-processing system.
Valid means the document additionally conforms to a schema: an XSD, a DTD, a RELAX NG grammar. The schema is what says an <order> must contain a <customerId> followed by one or more <lineItem> elements, that <quantity> holds a positive integer, and that <banana/> is not a thing. Schema validation needs the schema, so it cannot be inferred from the document alone. That is a separate job from this tool — but it is also almost never where your problem is. Fix well-formedness first; a document that fails well-formedness cannot even be handed to a schema validator.
When the document is malformed, the banner shows the browser's XML parser error. Chrome and Safari both use the same underlying parser, so their messages are worded identically; Firefox phrases the same problems differently but points at the same place. Here is what the common messages actually mean.
Input:
<a><b>hi</a>
Error: Opening and ending tag mismatch: b line 1 and a
Read it as: "I was inside b, and the next closing tag I met was a." The named element in the first position is the one you forgot to close. Two causes dominate: a genuinely missing </b>, and overlapped rather than nested tags — <b><i>text</b></i>. XML has no tolerance for the overlap that browsers forgive in HTML. Beautifying the document before you hunt makes this obvious, because the indentation stops going back to the left where you expected it to.
Input:
<a><B>hi</b></a>
Error: Opening and ending tag mismatch: B line 1 and b
XML is case-sensitive in a way HTML is not. <Book>, <book> and <BOOK> are three unrelated element names, and the same applies to attribute names. If a message names what looks like the same tag twice, look at the capitalisation before you look at anything else.
Input:
<a>Tom & Jerry</a>
Error: xmlParseEntityRef: no name
This impenetrable message means: an & started what the parser assumed was an entity reference, and no valid name followed it. In XML text content, & must be written & and < must be written <. Inside attribute values you additionally need " or ' for whichever quote character delimits the value. Five entities are predefined and always available: &, <, >, ", '. Anything else — , for instance, which people import out of HTML habit — is undefined in plain XML and produces its own error. Use the numeric form   instead.
Input:
<a/><b/>
Error: Extra content at the end of the document
An XML document has exactly one root element. Two siblings at the top level is not a document, it is two documents concatenated. This bites constantly when you paste a fragment out of a larger file, or when a log or export writes repeated records without a wrapper. The fix is to wrap the whole thing: <items><a/><b/></items>. The same message appears when stray text follows the closing root tag — a trailing log line, an accidental character, a second copy pasted below.
Input:
<a href=1></a>
Error: AttValue: " or ' expected
Every attribute value in XML is quoted, with no exceptions and no bare-number shortcut. Single and double quotes are both fine, and you pick whichever one is not inside the value.
Input:
<1a>x</1a>
Error: StartTag: invalid element name
Element names must start with a letter or underscore, never a digit and never a hyphen. After the first character, letters, digits, hyphens, underscores and periods are allowed but spaces are not. Names beginning with the letters xml in any capitalisation are reserved. This is the error you get when a generator interpolates a raw value straight into a tag name — a numeric record ID, say, producing <417> — and the fix is a prefixed name such as <id417> or, better, <record id="417"/>.
Error: PCDATA invalid Char value 12
XML 1.0 forbids most control characters outright. Tab, line feed and carriage return are permitted; the rest of the C0 range — including the form feed that produced the message above, and the null bytes and vertical tabs that leak in from legacy databases and fixed-width mainframe exports — cannot appear in an XML document at all, not even escaped as . Escaping does not rescue them, because the restriction is on the character, not the syntax. They have to be stripped or replaced at the source.
Error: Document is empty
Usually this means what it says, but it also appears when the file contains only whitespace, only a BOM, or when a fetch you thought succeeded returned nothing.
The XML declaration <?xml version="1.0" encoding="UTF-8"?> is optional, but if present it must be the very first thing in the file — character zero, no exceptions. A single space or newline in front of it produces XML declaration allowed only at the start of the document, and the error is maddening precisely because the offending character is invisible. If a file looks perfect and still fails on line 1, suspect leading whitespace.
A UTF-8 byte order mark is the other invisible culprit. A BOM at the very start of the file is tolerated — parsers recognise it and skip it. A BOM anywhere else is not: a stray BOM between the declaration and the root element yields Start tag expected, '<' not found, which sends people hunting for a missing angle bracket that is right there in front of them. BOMs get injected by Windows editors saving as "UTF-8 with BOM" and by naive file concatenation. Save as UTF-8 without BOM, or strip the leading bytes.
The encoding attribute is a declaration, not a conversion. If the file says encoding="US-ASCII" and the bytes are actually UTF-8, the parser reports an encoding or input-conversion error the moment it reaches the first non-ASCII byte — the é in café is enough. The label has to match the bytes. When in doubt, save as UTF-8 and declare UTF-8; it covers every character you are likely to need and is the default a parser assumes when no declaration is present.
Nothing in XML tells you whether a piece of data belongs in an attribute or a child element, and the argument is older than most of the people having it. The practical rules that hold up: attributes cannot repeat within an element, cannot contain child structure, and cannot hold newlines cleanly, so anything that might one day be a list, gain sub-fields, or run to multiple lines should be an element from the start. Attributes suit small, atomic, metadata-ish values — identifiers, units, type flags, language codes — and they keep documents compact. Order matters for elements and is meaningless for attributes, so if sequence carries information, use elements.
CDATA sections exist for the case where text content contains so many < and & characters that escaping every one would be unreadable: embedded HTML, a code snippet, a regular expression, a SQL query. Everything between <![CDATA[ and ]]> is taken literally, so <![CDATA[if (a < b) {}]]> parses cleanly with no escaping at all. The one thing a CDATA section cannot contain is the sequence ]]>, and there is no escape for it — you split into two CDATA sections instead. Note that CDATA is a convenience for humans, not a distinct data type: a parser hands your application the same string either way, and this formatter passes CDATA sections through untouched rather than trying to re-escape their contents.
Namespaces let one document combine vocabularies from different sources without name collisions — a <title> from Dublin Core and a <title> from your own schema can coexist. A prefix is bound with an xmlns: declaration and then used as prefix:localName: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">.
Three things routinely go wrong. First, using a prefix that was never declared — <a><ns:b/></a> — which produces Namespace prefix ns on b is not defined. This is the error you get after copying an element out of a SOAP envelope without bringing the envelope's declarations with it; paste the fragment into a wrapper that redeclares the prefix. Second, the prefix itself is not the identity — the URI is. Two documents using soap: and s: for the same URI are equivalent, and a tool that matches on the literal prefix string will silently miss elements. Third, a default namespace declared with plain xmlns="..." applies to unprefixed elements but never to unprefixed attributes, which is the subtlety that breaks hand-written XPath more than any other.
Because this formatter works on tokens rather than resolved names, prefixes and xmlns declarations pass through exactly as written — it will never helpfully "normalise" a prefix and change what your document means. It also means the well-formedness banner is the right place to catch an undeclared prefix, not the indentation.
An element with no content can be written <br/> or <br></br>, and the two are identical to a parser. What is not permitted is the HTML habit of an unclosed <br>, <img> or <meta> with no slash at all. HTML has a fixed list of void elements the parser knows about; XML has no such list, because it has no idea what your elements mean. Every element closes, one way or the other. This is the leading source of errors when someone feeds HTML to an XML parser, along with unquoted attributes and bare & in query strings.
The formatter is deliberately tolerant: it still produces indented output for a document that fails the well-formedness check, because seeing the structure is usually what helps you find the break. Trust the banner for correctness and the output pane for readability.
Beautify adds line breaks and indentation so the XML is easy to read. Minify removes the whitespace between tags to make the file as small as possible for transfer or storage. Neither changes your actual data.
It checks whether your XML is well-formed using the browser's native parser — meaning every tag is closed, properly nested, and there is a single root element. If something is wrong, it shows the parser error. It does not validate against a DTD or XSD schema.
No. Formatting, minifying, and validation all run locally in your browser with JavaScript. Your XML is never sent anywhere, which makes it safe for config files and private API payloads.
Yes. In Beautify mode you can format with 2 spaces, 4 spaces, or tabs, depending on your project's style conventions.