The problem: people confuse well-formed XML with valid XML, and neither means what they think
"Well-formed" and "valid" are different things in XML. Well-formed means the document follows the basic syntactic rules of XML: one root element, properly nested tags, all attributes quoted, all ampersands escaped, all tags closed. A parser can build a tree from it without choking. Valid means the document also conforms to a schema — a DTD, XSD, or RelaxNG file that defines which elements are allowed where, what attributes they can have, and what data types the values must be. A document can be well-formed but not valid (parseable but non-compliant), and it can be valid but not well-formed (compliant but syntactically broken — though this is rare in practice).
The XML Formatter checks well-formedness, not schema validity. It uses the browser's DOMParser to attempt a parse. If the parser returns a parsererror node, the tool reports the line and column where the error occurred. If the parse succeeds, the document is well-formed. The tool does not fetch or validate against any external schema — that requires a schema-aware parser like Xerces or libxml2 with schema support, which runs server-side.
Understanding this distinction matters because most XML errors people encounter are well-formedness errors, not schema violations. A missing closing tag, an unescaped ampersand in a URL, an unquoted attribute value — these are the things that break XML parsing in practice. Schema validation is a separate concern that most developers handle with a dedicated validator or a build step, not a formatter.
Fastest path
Open the XML Formatter, paste your XML into the input area, and the tool validates it immediately. If the XML is well-formed, the Formatted view shows the beautified output with syntax highlighting and line numbers. If it is not, the validation banner shows the error with line and column numbers. Use the indentation selector (2 spaces, 4 spaces, tabs) to control the output style. Switch to Tree view to see the DOM structure, JSON view for XML-to-JSON conversion, or Minified view to compress the output.
What well-formed XML requires
The XML specification defines five rules that make a document well-formed. The tool checks all of them through DOMParser:
- Single root element. The document must have exactly one top-level element.
<a/><b/>is not well-formed — it has two roots.<?xml version="1.0"?><root><a/><b/></root>is well-formed. - Properly nested tags.
<a><b></a></b>is not well-formed — the tags cross.<a><b></b></a>is well-formed. The closing tag order must mirror the opening tag order. - Quoted attribute values.
<a b=c>is not well-formed.<a b="c">and<a b='c'>both are. Single and double quotes are both valid. - Escaped ampersands and angle brackets in text. An ampersand in text content must be written as
&. A less-than must be<.Tom & Jerryin a text node breaks parsing.Tom & Jerrydoes not. The tool's pre-DOMParser check flags unescaped ampersands as warnings before the parser sees them. - All tags closed. In XML, unlike HTML, every opening tag must have a closing tag or be self-closing.
<br>is valid HTML but not well-formed XML.<br/>or<br></br>is well-formed.
The tool's validation runs in two phases. First, it scans line-by-line for unescaped ampersands and unquoted attribute values — these are flagged as warnings. Then it passes the input to DOMParser, which checks all five rules. If DOMParser returns a parsererror node, the tool extracts the line number, column number, and error message from the parser's error output.
Formatting: re-serializing from the parsed tree
Formatting XML is not a text transformation. The tool parses the input into a DOM tree using DOMParser, then walks the tree and serializes it back to text with consistent indentation. This means the formatted output is structurally identical to the input but cosmetically normalized — whitespace between tags is replaced with the chosen indentation, attributes are consistently spaced, and empty elements are rendered in the chosen style.
The formatting options control the output:
- Indent size: 2 spaces, 4 spaces, or tabs. The default is 2 spaces.
- Empty element style: self-closing (
<tag/>) or explicit (<tag></tag>). Both are valid XML. Self-closing is more compact. Explicit is required by some legacy parsers that do not handle self-closing tags correctly. - Attribute formatting: inline (all attributes on one line) or multiline (one attribute per line, for elements with 3 or more attributes). Multiline is useful for configuration files where individual attributes need to be readable.
- Sort attributes: alphabetically sorts attribute names within each element. This is useful for diffing two XML files — sorted attributes produce smaller, more consistent diffs.
- Preserve comments: when enabled, comments are retained in the formatted output with proper indentation. When disabled, comments are stripped.
The tool preserves the XML declaration (<?xml version="1.0" encoding="UTF-8"?>) and DOCTYPE declarations from the original input, extracting them via regex before formatting and prepending them to the output. DOMParser consumes these during parsing, so they must be re-injected.
Minifying: regex-based compression, not re-serialization
Minification takes a different approach. Instead of parsing and re-serializing, the tool applies regex transformations to the raw string:
- Remove comments: strips
<!-- ... -->blocks. - Remove whitespace: collapses
> <to><, removes leading and trailing whitespace, collapses internal whitespace to single spaces. - Collapse empty tags: converts
<tag></tag>to<tag />. - Remove XML declaration: strips
<?xml ... ?>.
The minified output is functionally equivalent to the original for any XML parser. The savings come from removing whitespace and comments, which can be significant for large configuration files or SOAP responses. The tool shows the character count before and after, along with the percentage savings.
Minification is regex-based rather than parser-based because the goal is speed and simplicity — there is no need to build a DOM tree just to remove whitespace. The tradeoff is that regex minification cannot detect semantic whitespace (whitespace inside CDATA sections or mixed-content elements where text spacing matters). For most XML documents (config files, data feeds, SOAP responses), this is not a problem. For XHTML or DocBook with mixed content, it can be.
XML to JSON conversion
The tool converts XML to JSON using a set of conventions that are common but not standardized:
- Element names become JSON object keys.
- Attributes are prefixed with
@.<book id="bk101">becomes{"book": {"@id": "bk101"}}. - Text content goes under a
#textkey.<title>XML Guide</title>becomes{"title": {"#text": "XML Guide"}}. - Repeated child elements become arrays. Two
<book>elements inside<catalog>produce{"catalog": {"book": [{...}, {...}]}}. A single<book>produces{"catalog": {"book": {...}}}— an object, not an array. This is a known inconsistency in XML-to-JSON conversion: the cardinality of child elements affects the JSON structure, and XML does not declare cardinality. - Comments go under
#comment. CDATA goes under#cdata.
This conversion is useful for getting XML data into a format that JavaScript can work with naturally. The JSON Formatter can then prettify the JSON output. The tradeoff is that XML features not present in JSON — namespaces, processing instructions, mixed content — are either lost or awkwardly represented.
XPath: querying the parsed tree
The tool supports XPath queries against the parsed document. XPath is a path expression language for selecting nodes from an XML document. The basics:
/root/childselects a child element at a specific path.//elementselects elements anywhere in the document, regardless of position.//element[@attribute='value']selects elements with a specific attribute value (the@prefix denotes attributes).//element[1]selects the first element by position.//element[last()]selects the last.//element/text()returns the text content of selected elements.count(//element)returns the number of matching elements as a number.string-length(//element)returns the character length of the element's text content.
The tool runs queries via doc.evaluate(), the browser's native XPath implementation. Results are categorized as elements (showing the outerHTML), attributes (showing name and value), text, or scalar values (for functions like count). Each result includes its XPath path — a computed path like /catalog/book[1]/title that tells you exactly where the node lives in the tree.
Namespaces break XPath unless you handle them. If your XML uses namespaces (xmlns="http://example.com" or xmlns:dc="http://purl.org/dc/elements/1.1/"), a bare //book query will not match <book> elements in a default namespace. The tool has a "Handle Namespaces" toggle that extracts all namespace declarations from the document and registers them with the XPath resolver. With this enabled, you can query prefixed elements like //dc:author. Without it, namespace-prefixed queries return no results.
Gotchas
- The tool checks well-formedness, not schema validity. A document that passes validation may still violate a schema's rules (wrong element order, missing required attributes, incorrect data types). The tool cannot catch these because it does not load schemas. Use a schema validator like
xmllint --schemaor an online XSD validator for schema compliance. - Minification uses regex, not the parser. Whitespace inside CDATA sections and mixed-content elements is preserved literally by the parser but may be altered by the regex minifier. If your XML has mixed content (text and elements interleaved), minify with caution. Pure data XML (config files, feeds, SOAP) minifies safely.
- XML-to-JSON cardinality is inconsistent. A single child element becomes an object. Two or more children with the same name become an array. Code consuming the JSON must handle both cases. This is a fundamental mismatch between XML (which does not declare cardinality) and JSON (which does distinguish objects from arrays).
- Namespaces make XPath harder. Elements in a default namespace (
xmlns="..."with no prefix) cannot be selected by bare name in XPath 1.0, which is what browsers implement. You need to register the namespace with a prefix and use that prefix in your query, even though the XML itself does not use a prefix for those elements. The tool's namespace toggle handles this, but you need to know what prefix to use in your query. - Self-closing vs explicit empty tags is a style choice, not a correctness issue.
<tag/>and<tag></tag>are semantically identical in XML. The tool lets you choose, but some XML consumers (notably older SOAP stacks and some XML databases) have bugs with one form or the other. If you are feeding XML to a legacy system, check which form it expects.
Summary
- Well-formed XML follows five syntactic rules (single root, proper nesting, quoted attributes, escaped entities, closed tags). Valid XML additionally conforms to a schema. The tool checks well-formedness via DOMParser — it cannot validate against schemas.
- Formatting parses the XML into a DOM tree and re-serializes it with consistent indentation. This normalizes whitespace and structure. Minification uses regex to strip comments, collapse whitespace, and collapse empty tags — it is faster but less safe for mixed-content XML.
- XML-to-JSON conversion uses the @ prefix for attributes, #text for text content, and arrays for repeated children. Cardinality is inconsistent — single children are objects, multiple children are arrays. Use the JSON Formatter to prettify the output.
- XPath selects nodes via path expressions. Namespaces break queries unless registered. The tool's namespace toggle handles this. Common patterns:
//element[@attr='val']for attribute filtering,//element[1]for positional selection,count(...)for counting. - Use the XML Formatter for formatting, validation, tree view, XPath queries, and XML-to-JSON conversion, the JSON Formatter for JSON beautification, the CSS Minifier for minifying CSS and JavaScript, and the Diff Checker to compare formatted and original XML.