XML Formatter

Formatted in your browser and never transmitted. Mixed content is left inline rather than re-indented, because adding line breaks around text changes what the document says. Attribute order and quoting are preserved, and no XML declaration is invented.

Nothing you enter here is stored, logged or shared.

Paste XML to indent it readably or collapse it to one line, and to check that it is well formed. Errors point at the exact line and column. Everything runs in your browser, so nothing is uploaded.

How to use

  1. Paste your XML into the input field.
  2. Choose Format or Minify, and set the indent width if you want.
  3. Copy the result, or read the error with its line and column.

Well formed is not the same as valid

XML has two separate notions of correctness and they are routinely confused. Well formed means the document obeys the syntax: one root element, every tag closed by a matching tag, attributes quoted, comments and CDATA terminated, no stray text outside the root. It is checkable from the document alone, and it is what this tool reports.

Valid means the document also conforms to a schema - a DTD, an XSD, or a RelaxNG grammar - that says which elements may appear, in what order, how often, and what their attribute values may look like. That check is impossible without the schema, and a document can be perfectly well formed while being nonsense against the grammar it claims to follow.

Namespaces sit slightly to one side of both. A prefix used without a matching xmlns declaration is a namespace error rather than a well-formedness error, so a document can pass the syntax check and still be rejected by a namespace-aware parser. If a SOAP or Office document is being refused despite formatting cleanly, an undeclared prefix is worth checking early.

Whitespace is sometimes data

This is the rule that governs everything the formatter does. Whitespace between elements is almost always layout, and replacing it with different layout changes nothing. Whitespace inside mixed content - text and elements as siblings, as in a paragraph with a bold word in it - is part of the text, and reflowing it changes the document.

So elements containing mixed content are left exactly as written, even when that leaves a long line in the middle of an otherwise indented document. The alternative is what most formatters do: indent everything, insert a line break between Hello and <b>there</b>, and produce a document that renders with a gap that was not there before. It looks tidier and it is wrong.

The specification provides xml:space="preserve" for declaring this explicitly, and it is worth using on any element whose text content is significant. Note that it is inherited by descendants until overridden, which surprises people who set it once at the root.

What actually breaks XML documents

An unescaped ampersand is the most common by a wide margin. In XML, & starts an entity reference, so a raw one in a URL query string or a company name makes the document ill formed. It must be written &amp;, and a less-than sign in text must be &lt;. There are only five predefined entities - amp, lt, gt, quot and apos - and anything else must be declared or written as a numeric character reference.

Encoding mismatches come next. The declaration at the top of the file states what encoding the bytes are in, and if the file was later saved as something else the parser will read multi-byte characters as garbage or fail outright. A byte order mark ahead of the declaration causes its own failures in some parsers. Related: a handful of control characters are simply not permitted in XML 1.0 at all, not even escaped, so binary data that has leaked into a text field cannot be rescued by encoding it - it has to be removed or base64 encoded.

Then there is HTML habit. Unquoted attribute values, unclosed tags like <br>, and duplicate attributes are all fine in HTML and all fatal in XML. If a document came from an HTML source, those are the first things to look for.

Entities, and a note on parsing untrusted XML

XML lets a document declare its own entities in a DTD, including external ones that point at a file path or a URL. This is the basis of two well-known attack classes, and they are worth knowing about even if you only ever consume XML rather than write it.

XML external entity injection uses a declared entity pointing at a local file to make a server read that file and return its contents in the response - historically a reliable way to extract configuration and credentials from anything that parsed uploaded XML with default settings. The billion laughs attack nests entities so that each expands into several of the next, so a few kilobytes of input expands to gigabytes in memory.

The defence in both cases is to disable DTD processing and external entity resolution in your parser. Most modern libraries default to safe now, and plenty of older code does not. This page resolves nothing external: it reads the document as text and never fetches anything it refers to.

Namespaces, and why prefixes are not names

A namespace binds a prefix to a URI, and it is the URI that identifies the element - the prefix is a local shorthand that can be renamed freely. Two documents using soap: and s: for the same URI are equivalent, and two documents both using ns1: for different URIs are not. Code that matches on the prefix rather than the URI works until somebody reformats the document.

A default namespace declared with xmlns applies to elements but not to attributes, which is the rule most people get wrong. An unprefixed attribute belongs to no namespace at all, regardless of what the enclosing element declares, which is why xsi:type and xml:lang are always written with a prefix.

When a parser rejects a document that looks well formed, an undeclared prefix is the usual cause. Formatting will succeed, because prefix binding is a namespace rule rather than a syntax rule, and the failure appears later in whatever consumes the document.

Schemas, and what validation actually gives you

Well-formedness is syntax; validity is conformance to a grammar. DTD is the original mechanism, limited and still used for entity declarations. XSD is the dominant one - itself written in XML, expressive about data types, and verbose enough that reading one is a skill. RelaxNG is far more pleasant to write and less widely supported, which is the usual trade.

What a schema buys is a contract that can be checked mechanically at the boundary, before your code sees the data: required elements present, numbers where numbers belong, enumerated values inside their set. In integrations with partners, the schema is frequently the only specification that both sides agree on.

Validating in a pipeline is a matter of one command - xmllint --schema schema.xsd file.xml --noout - and the error messages point at a line and an element. The reason to do it at the edge rather than in application code is that a schema failure is a clean rejection with a reason, while the same problem found three layers in is a stack trace.

Getting data out with XPath

XPath is the query language for XML and it is worth an hour of anyone's time. //book/title selects every title element under a book anywhere in the document; //book[@id='b1'] selects by attribute; //book[price>30]/title filters on a child's value. It is the addressing language underneath XSLT, Java's XML tooling, Python's lxml, and most browser automation.

Namespaces are where XPath gets awkward. An expression has to bind the prefixes it uses, and in a document with a default namespace the elements are in that namespace even though they appear unprefixed, which is why //book matches nothing and everybody's first XPath against a SOAP response comes back empty. Tools vary in how they let you register the binding, and the local-name() function is the crude escape hatch.

XSLT is the transformation language built on top of it, and it remains the most practical way to convert one XML vocabulary into another - or into HTML - without writing procedural code. Its reputation for difficulty is mostly about the functional style, not the syntax.

XML is still everywhere

Office documents are XML: a .docx or .xlsx is a zip archive containing a directory of XML parts, which is why a corrupt document can sometimes be repaired by unzipping it and fixing one file. SVG is XML, so an icon can be edited with a text editor and generated by a template. RSS and Atom feeds are XML, and so is the sitemap this site publishes.

In enterprise and government integration, SOAP is far from dead: banking, insurance, healthcare through HL7, and customs and tax systems in most countries run on XML with schemas and, frequently, signed payloads. XML Signature and XML Encryption allow a single element to be signed within a larger document, which JSON has no standard equivalent for.

Android layouts, Maven builds, .NET configuration and countless CI descriptions are XML too. The format is unfashionable rather than obsolete, and the ability to read one comfortably is a durable skill.

Parsing XML you did not write

The defaults in many XML libraries are unsafe for untrusted input, and the reason is the entity mechanism. External entities let a document reference a local file or a URL, so a server that parses uploaded XML with default settings can be made to read /etc/passwd and return it - the XXE attack, still found in production systems years after it was catalogued.

Expansion is the other side. The billion laughs attack nests entities so that a few kilobytes of input expands to gigabytes in memory, taking down the process. Neither attack needs anything unusual: both are ordinary XML using features the specification defines.

The defence is one line in most libraries - disable DTD processing and external entity resolution - and it is worth confirming rather than assuming, since defaults differ by language and version. This page resolves nothing external at all: it reads the document as text and never fetches anything it refers to.

Frequently asked questions

Why does some of my XML stay on one line?
Because it contains mixed content - text sitting alongside elements, as in "Hello <b>there</b>." Indenting that would insert line breaks and spaces into the text itself, so a renderer would show "Hello there ." with a stray gap. Those elements are therefore left exactly as written. Most XML formatters reflow them anyway and quietly change the document.
Does formatting ever change what my document means?
No, and that is the point of the rule above. Whitespace between elements is layout and gets replaced; whitespace inside mixed content is data and is preserved. Attribute order and quote style are kept exactly as written, comments and CDATA are copied through untouched, and no XML declaration is added if the document did not have one.
What does "well formed" actually check?
That every element is closed by a matching tag, that attribute values are quoted, that comments and CDATA blocks are terminated, and that there is exactly one root element with no stray text outside it. It does not validate against a DTD or schema - that would need the schema, which is a different tool.
Why was my attribute rejected?
XML requires quotes around every attribute value. HTML lets you write disabled=true or width=100 and browsers cope, but XML does not, and every parser downstream will reject it. If the document came from an HTML source, that is usually the first thing to fix.
What is the difference between minify and format?
They are opposites over the same document. Format inserts line breaks and indentation between elements so it can be read; minify removes all of it so the document is as small as possible for transport. Neither touches mixed content, so running one after the other returns you to where you started.
Is my XML uploaded anywhere?
No. The parsing and formatting happen in your browser, so configuration files, SOAP payloads and export dumps - which frequently contain internal hostnames, identifiers and personal data - never leave your machine.

Last updated:

Report a problem

Include the steps, expected result, and actual result. Remove secrets and personal data.

Related tools