SyntaxStudy
Sign Up
XML Well-Formed vs Valid XML Documents
XML Beginner 1 min read

Well-Formed vs Valid XML Documents

Well-formedness is the minimum requirement for an XML document. A parser that encounters a non-well-formed document is required to stop and report a fatal error — unlike HTML parsers, which apply error recovery heuristics. The well-formedness constraints include: exactly one root element, every start tag matched by an end tag (or self-closed), elements properly nested without overlap, attribute names unique within a tag, and attribute values enclosed in single or double quotes. Validity is a stricter requirement. A valid document is well-formed and additionally conforms to a grammar that defines permitted element names, the allowed structure of child elements, which attributes exist on each element, and the data type of attribute values and text content. Two schema languages are commonly used: Document Type Definitions (DTD), which are part of the XML specification itself, and XML Schema Definition (XSD), a more powerful W3C standard that supports data types and namespaces. Validation is performed by a validating XML parser. Non-validating parsers — like most browser XML parsers — only check well-formedness. Understanding which mode a tool operates in is important: a document can be well-formed but invalid (it parses without error but violates the schema), whereas a valid document is always well-formed by definition.
Example
<!--
    WELL-FORMED: passes basic XML syntax rules
    VALID: also conforms to a DTD or schema
-->

<!-- WELL-FORMED (correct) -->
<person>
    <name>Alice</name>
    <age>30</age>
</person>

<!-- NOT WELL-FORMED: overlapping elements -->
<!--
<person>
    <name><bold>Alice</name></bold>
</person>
-->

<!-- NOT WELL-FORMED: missing closing tag -->
<!--
<person>
    <name>Alice
</person>
-->

<!-- NOT WELL-FORMED: unquoted attribute -->
<!--
<person id=42>
    <name>Alice</name>
</person>
-->

<!-- WELL-FORMED but NOT VALID against a schema
     that only allows <name> and <age> as children -->
<person>
    <name>Alice</name>
    <age>30</age>
    <nickname>Al</nickname>
</person>