XML Formatter and Validator

Indent XML without changing what it means: mixed content, CDATA and xml:space="preserve" blocks come out byte-for-byte as they went in.

Input

Settings

History

Load from URL

XML is still everywhere

REST moved most new APIs to JSON, but XML remains the format of SOAP services, SAML assertions, RSS and Atom feeds, Maven pom.xml, .NET .csproj and web.config, Android layouts, Office Open XML internals, XSLT stylesheets and countless bank and government interfaces. Those documents usually arrive as a single minified line in a log or an HTTP trace.

The formatter here is a purpose-built XML tokenizer and printer rather than a generic HTML beautifier. It checks well-formedness (matching tags, one root element, quoted attributes, legal & usage) and reports problems with the line and column where they start, plus a hint naming the element that is probably missing its closing tag.

Using the formatter

Drop in a file (.xml, .xsd, .wsdl, .rss, .plist, .config and more are recognised) or paste the text; a leading <?xml or root element is enough for auto-detection. Ctrl/Cmd+Enter formats and Ctrl/Cmd+Shift+M minifies. Use Ctrl/Cmd+Shift+C to copy and Ctrl/Cmd+K for the palette, where you can open the Tree view or convert the document to JSON or YAML. SAML responses and SOAP payloads often carry personal data, and they stay in your browser tab during all of this.

Options

  • Wrap attributes above: when an element has more than this many attributes, each goes on its own line. The default, 0, wraps only when the start tag would exceed the line width. Setting it to 2 gives the one-attribute-per-line look common in Android layouts and Spring XML.
  • Empty elements: As written keeps <tags/> and <tags></tags> as they are. Self-close <a/> shortens every empty element, while Expand <a></a> writes an explicit end tag — some older parsers and XHTML-served-as-HTML need that form.
  • Space before /> prints <br /> instead of <br/>.
  • Collapse whitespace-only elements turns an element containing only spaces and newlines into an empty element. SVG <text> and XSLT <xsl:text> are exempt because their whitespace is output.
  • Keep comments when minifying: Minify removes comments by default; turn this on for files where comments carry meaning, such as license headers.

Sort keys sorts attributes alphabetically, with namespace declarations first. Indent and line width work as on every other page.

Whitespace, CDATA and entities

In XML, whitespace inside text is data. The printer only adds or removes indentation between child elements of element-only content. Three cases are printed inline and verbatim:

  • Mixed content such as <p>Total: <b>42</b> items</p>, where re-indenting would insert spaces into the text.
  • Elements with xml:space="preserve" and everything inside them.
  • CDATA sections, which are copied exactly, including any < or & they contain.

The XML declaration, DOCTYPE, comments and processing instructions are also written exactly as found.

Entities are never expanded. &company; declared in an internal DTD stays &company; in the output. This makes the tool immune to XXE and “billion laughs” entity attacks, and it means your document is not altered. A reference to an entity that is not declared anywhere, such as HTML’s &nbsp;, produces a warning that suggests the numeric form &#160;.

Byte-order marks are removed with a note.

Examples

SOAP response from a payment gateway

The namespaced envelope is indented one level per element while the CDATA message is copied unchanged.

Input
<?xml version="1.0" encoding="UTF-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:pay="https://api.example-bank.com/payments/v2"><soap:Header><pay:RequestId>7f3c2a90-1b4e</pay:RequestId></soap:Header><soap:Body><pay:AuthorizeResponse><pay:Status>APPROVED</pay:Status><pay:AuthCode>A81F22</pay:AuthCode><pay:Amount currency="EUR">249.00</pay:Amount><pay:Message><![CDATA[Approved <3DS frictionless> & captured]]></pay:Message></pay:AuthorizeResponse></soap:Body></soap:Envelope>
Output
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope
  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:pay="https://api.example-bank.com/payments/v2">
  <soap:Header>
    <pay:RequestId>7f3c2a90-1b4e</pay:RequestId>
  </soap:Header>
  <soap:Body>
    <pay:AuthorizeResponse>
      <pay:Status>APPROVED</pay:Status>
      <pay:AuthCode>A81F22</pay:AuthCode>
      <pay:Amount currency="EUR">249.00</pay:Amount>
      <pay:Message><![CDATA[Approved <3DS frictionless> & captured]]></pay:Message>
    </pay:AuthorizeResponse>
  </soap:Body>
</soap:Envelope>
Open this example in the tool

Maven pom.xml dependency block

A collapsed POM becomes the familiar one-element-per-line layout, and the comment is kept in place.

Input
<project xmlns="http://maven.apache.org/POM/4.0.0"><modelVersion>4.0.0</modelVersion><groupId>com.example.shop</groupId><artifactId>orders-service</artifactId><version>2.4.0</version><!-- runtime deps --><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId><scope>runtime</scope></dependency></dependencies></project>
Output
<project xmlns="http://maven.apache.org/POM/4.0.0">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example.shop</groupId>
  <artifactId>orders-service</artifactId>
  <version>2.4.0</version>
  <!-- runtime deps -->
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <scope>runtime</scope>
    </dependency>
  </dependencies>
</project>
Open this example in the tool

Android layout with one attribute per line

Elements with more than two attributes get one per line, and the empty Button is shortened to a self-closing tag with a space before the slash.

Input
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"><TextView android:id="@+id/order_total" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18sp"/><Button android:id="@+id/checkout" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/checkout"></Button></LinearLayout>
Output
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical">
  <TextView
    android:id="@+id/order_total"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="18sp" />
  <Button
    android:id="@+id/checkout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/checkout" />
</LinearLayout>
Open this example in the tool

RSS feed item with preserved whitespace

The xml:space=“preserve” element keeps its leading spaces and line break exactly, while its siblings are indented normally.

Input
<rss version="2.0"><channel><title>Release notes</title><item><title>v2.4.0</title><pubDate>Mon, 14 Sep 2026 08:00:00 GMT</pubDate><description><![CDATA[<p>Faster <b>checkout</b> &amp; refunds.</p>]]></description><pre xml:space="preserve">  npm install @shop/sdk@2.4.0
  npm test</pre></item></channel></rss>
Output
<rss version="2.0">
  <channel>
    <title>Release notes</title>
    <item>
      <title>v2.4.0</title>
      <pubDate>Mon, 14 Sep 2026 08:00:00 GMT</pubDate>
      <description><![CDATA[<p>Faster <b>checkout</b> &amp; refunds.</p>]]></description>
      <pre xml:space="preserve">  npm install @shop/sdk@2.4.0
  npm test</pre>
    </item>
  </channel>
</rss>
Open this example in the tool

Common errors and how to fix them

ErrorCauseFix
Expected </item> to close <item> opened at line 4, found </channel>
Explained
An element was never closed, or two closing tags are in the wrong order. XML tag names are also case-sensitive, so </Item> does not close <item>.Add the missing closing tag where the element should end; the hint names the element that is still open.
Unescaped '&' — it must start an entity reference like &amp; or &#38;
Explained
A literal ampersand appears in text or an attribute, typically in a URL query string or a company name like “Smith & Sons”.Write & instead, or wrap the text in a CDATA section.
Only one root element is allowed — <order> follows the root element <order> that closed at line 9
Explained
Two XML documents were concatenated, as happens when you copy several messages from a log.Format one document at a time, or wrap them in a single parent element.
Text is not allowed before the root element
Explained
Something precedes the first tag: a log prefix, an HTTP header line or stray characters from a copy.Delete everything before the XML declaration or root element.
Entity &nbsp; is not declared (only &amp; &lt; &gt; &quot; &apos; are built in)
Explained
HTML named entities are not defined in XML. This is a warning; the document still formats.Use the numeric reference   or declare the entity in the DOCTYPE.
The value of attribute 'qty' must be in quotes
Explained
An attribute was written HTML-style without quotes, as in <item qty=2>.Quote the value: qty=“2”.

Frequently asked questions

Does pretty-printing change my XML data?

Only whitespace between child elements of element-only content changes. Text, mixed content, CDATA, comments and xml:space=“preserve” blocks are copied exactly, so a schema-validated document stays valid.

How do I format XML in Notepad++?

Install the XML Tools plugin from Plugins > Plugins Admin, then use Plugins > XML Tools > Pretty print. For a one-off file, pasting it here is faster and also shows a tree view.

Can the validator check my XML against an XSD schema?

Not yet. This page checks well-formedness (the rules every XML document must follow); validating against an XSD or DTD needs a schema-aware tool such as xmllint --schema.

Is it safe to paste a SAML response or SOAP message?

Yes. The document is parsed in your browser and nothing is uploaded, and because entities are never expanded, a hostile DTD cannot read files or exhaust memory.

How do I convert XML to JSON?

Use the XML to JSON converter. Attributes become @-prefixed keys and repeated elements become arrays; comments and processing instructions are dropped because JSON has no equivalent.

Related tools