XML: Well-Formed vs Valid, and What the Checker Catches
"Is this valid XML?" is two questions. The checker on this site answers only the first.
| Question | Defined by | Needs |
|---|---|---|
| Is it well-formed? | The XML 1.0 syntax rules | Just the text |
| Is it valid? | A DTD or a schema (XSD, RELAX NG) | The document and the schema |
A parser must refuse a document that is not well-formed. A document that is well-formed but invalid is a different failure that only a schema-aware validator reports.
What makes a document not well-formed
| Error | Example | Why it is fatal |
|---|---|---|
| Mismatched or missing close tag | <a><b></a> | Nesting must be strict. |
| Two roots | <a/><b/> | A document has exactly one root element. |
| Unquoted attribute | <a x=1/> | HTML allows it; XML does not. |
| Duplicate attribute | <a x="1" x="2"/> | Attribute names are unique per element. |
| Bare ampersand | <a>Tom & Jerry</a> | & starts an entity reference; write &. |
| Unknown entity | <a> </a> | Only & < > " ' and numeric references exist unless a DTD defines more. |
< in an attribute value | <a t="a<b"/> | Must be <. |
| Text outside the root | hello <a/> | Only comments, processing instructions and whitespace are allowed there. |
| Declaration not first | whitespace before <?xml ...?> | The declaration must be the first thing in the file. |
The checker reports the first of these it meets, with line and column, then stops. Fix it and run again: later errors are often consequences of the first one.
The named-entity trap
, © and — are HTML entities. Pasting HTML-flavoured text into an XML payload is the most common reason a feed or SOAP body is rejected. Use the numeric form ( , ©, —) or the character itself in a UTF-8 document.
What passes here and can still fail
- A required element is missing, or an element appears in the wrong order for the XSD.
- An attribute has a value outside the schema's allowed set or type.
- A namespace URI is wrong. To the checker
soap:Envelopeis just a name; a mismatched namespace is a schema or application error.
For those, use xmllint --noout --schema schema.xsd file.xml.