XML vs HTML: well-formedness, void elements, and why parsers differ
HTML and XML look like siblings: both use angle brackets, tags, and attributes. They are not. HTML is a specific vocabulary with a forgiving parser designed to render broken markup anyway. XML is a general syntax with a strict parser designed to reject anything malformed. The shared appearance hides a philosophy that is nearly opposite, and most confusion between the two comes from treating one by the other's rules.
Well-formedness: the dividing line
XML has a concept called well-formedness. A well-formed document obeys a short list of hard rules: every start tag has a matching end tag, elements nest without overlapping, there is exactly one root element, attribute values are quoted, and a handful of characters like < and & are escaped. A document that breaks any of these is not XML at all, and a conforming parser must refuse it with a fatal error, not guess.
HTML has no equivalent demand. The HTML parsing algorithm in the living standard is a long specification of how to recover from mistakes: unclosed tags, misnested elements, missing quotes, stray characters. The browser builds a DOM regardless. This is why a page with a forgotten </div> still renders. The leniency is deliberate, because the web is full of imperfect markup and a browser that refused to render it would be useless.
The differences that bite
| Aspect | XML | HTML |
|---|---|---|
| Malformed input | Fatal error, parsing stops | Recovered, DOM built anyway |
| Case sensitivity | <Note> and <note> are different | Tag and attribute names are case insensitive |
| Closing tags | Every element must close | Many may be omitted |
| Unknown tags | Fine, any name is valid | Parsed as unknown elements, still allowed |
| Entities | Only five predefined (< > & ' ") plus declared ones | Hundreds of named entities like © |
| Root element | Exactly one required | Tolerant |
Void elements and self-closing tags
This is the single most common source of cross confusion. HTML has void elements: <br>, <img>, <input>, <hr>, <meta>, <link>, and a few more. These never have content and never take a closing tag. In HTML you write <br>, not <br></br>. Writing <br>...</br> is invalid because </br> is not a thing.
XML has no void elements. Every element either has a closing tag or uses the self-closing shorthand <tag/>, which is exactly equivalent to <tag></tag>. So in XML you must write <br/> or <br></br>.
The trailing slash in HTML is where the confusion lands. In HTML, <br/> is accepted on void elements but the slash is ignored, it does nothing, it is there only for people coming from XML habits. On a non void HTML element, the slash is also ignored, which means <div/> does not self close. The browser treats it as an open <div> and keeps nesting everything that follows inside it, often producing a surprising DOM. In XML, <div/> would be a properly closed empty element. Same characters, different outcome.
XHTML: the strict middle
XHTML was HTML expressed as well-formed XML, served as application/xhtml+xml, parsed by an XML parser with all its strictness. In that mode a single unclosed tag yields a parse error and a blank page rather than a rendered document. XHTML is largely historical now; HTML5 is the mainstream, and it is parsed by the lenient HTML algorithm even when written in a tidy, XML like style. Writing <br/> in an HTML5 document is harmless but it does not make the parser strict.
The takeaway for working with both
Treat them by their own rules. When you generate XML, it must be well-formed or downstream parsers reject it: close every tag, escape & and <, quote attributes, keep one root. When you write HTML, rely on the browser's tolerance but do not depend on self-closing non void elements, because the slash is a no op and <div/> will not close. And never run XML through an HTML parser or HTML through an XML parser expecting correct results; the entity sets, case handling, and error behavior all differ.
To check whether a document is actually well-formed, and to see its structure cleanly, paste it into the XML Formatter, which validates and indents it locally in your browser.