XML formatter

Paste XML and it lays itself out — text and attributes stay untouched.

How to use it

  1. Paste your XML into the box — it is formatted as you type, there is no button to press.
  2. Pick Format or Minify, and 2 or 4 spaces for indentation; the result updates immediately.
  3. If the structure is broken, the message names the line, the column and the element. Copy the result or download it as a .xml file.

Example

Input

<?xml version="1.0" encoding="UTF-8"?><order id="A-1042"><customer><name>Ada Lovelace</name><email>ada@example.com</email></customer><items><item sku="X-1" qty="2">Analytical Engine gear</item><item sku="X-2" qty="1">Punch card set</item></items></order>

Formatted

<?xml version="1.0" encoding="UTF-8"?>
<order id="A-1042">
  <customer>
    <name>Ada Lovelace</name>
    <email>ada@example.com</email>
  </customer>
  <items>
    <item sku="X-1" qty="2">Analytical Engine gear</item>
    <item sku="X-2" qty="1">Punch card set</item>
  </items>
</order>

Default rules only: one element per line, two spaces per level. Attribute order, quotes and values are untouched, and so is the text inside <name>.

Rules, limits and known issues

  • Structure check only: tag pairing, attribute quoting/duplication/separation, element and attribute names, entity syntax. No DTD or XSD validation, no entity expansion, no namespace-prefix binding check.
  • Only structural whitespace is rewritten — the whitespace between attributes and the whitespace that makes up an element that has no text. Attribute order, quote style, values, entities, comments, CDATA and the DOCTYPE internal subset are copied character for character.
  • Mixed content is never re-indented: in <p>Hi <b>there</b>!</p> the spacing is kept as typed, because adding line breaks would change the text. The same applies to xml:space="preserve", which is copied verbatim.
  • Empty elements keep the form you typed: <a></a> is not collapsed to <a/>, and <a/> is not expanded. Attributes are not sorted and quotes are not unified.
  • Minify deletes structural whitespace only. Text whitespace, comments, CDATA and the DOCTYPE are kept — nothing is removed from your content.
  • An unclosed tag, comment, CDATA or DOCTYPE at the very end of the input is reported as a warning, not an error: you still get a result. Real mistakes (mismatched tags, unquoted attribute values, a stray "&") are errors with line and column.
  • A fragment (several top-level elements, or text outside the root) is formatted and reported as a fragment. Input with no element at all is an error.
  • Line and column numbers count Unicode code points, so an emoji is one column. Only space, tab, line feed and carriage return count as whitespace; U+3000 or U+00A0 inside text is content and is never removed.
  • No HTML: omitted end tags such as </li> or <br> are reported as unclosed. No file upload, no URL parameters, no history, no tree view, no XML→JSON. Everything runs in your browser: nothing is uploaded or stored.
  • Above 200,000 characters the result updates about 0.6 s after you stop typing; the text is never truncated. Output uses LF and has no trailing newline; formatting is idempotent.

What people usually need next, once the structure is readable.