XML file format
Extensible Markup Language, a general-purpose structured text format.
- MIME type
- application/xml
- Extensions
- .xml
- Category
- Text & markup
Magic-number signature
Plain text beginning with the '<?xml' declaration.
About the XML format
XML is a text format defined by a set of well-formedness rules rather than by any byte layout: one root element, every element closed, attribute values quoted, and a small set of characters that must be escaped. Everything else about a given XML document - what the elements are called, what nesting is legal, what any of it means - is defined outside the standard, by a schema or by a specification that happens to use XML as its syntax. That is why so many unrelated things are XML at once: Office documents, EPUB, RSS and Atom feeds, SVG, Android layouts, XMP metadata, sitemaps and property lists all are, and not one of them can read another.
Header layout, byte by byte
| Offset | Length | Field | Meaning |
|---|---|---|---|
| 0 | 3 | UTF-8 byte-order mark | EF BB BF, optional. It is the only thing the standard allows in front of the declaration; any other byte before the first angle bracket makes the document not well-formed, which is a rule worth memorising because it turns a whole class of bugs into a two-second hex check. |
| 0 | 2 | UTF-16 byte-order mark | FE FF for big-endian or FF FE for little-endian. Unlike the UTF-8 mark this one is not optional: the standard says entities encoded in UTF-16 must begin with a mark, while entities in UTF-8 merely may. UTF-16 XML is rare and breaks any tool that assumes one byte per character. |
| 0 | 5 | XML declaration opener | 3C 3F 78 6D 6C, the five characters that begin the declaration. It sits at offset 0, or at offset 3 behind a UTF-8 mark, and nowhere else. It is optional for UTF-8 content, which is exactly why no detector can insist on it and why so much XML has to be identified by its root element instead. |
| 0 | 4 | UTF-16 declaration without a mark | 00 3C 00 3F for big-endian and 3C 00 3F 00 for little-endian. The standard's autodetection appendix lists these patterns for a circular reason worth appreciating: a parser has to guess the encoding well enough to read the declaration that states the encoding. |
| 5 | variable | Declaration pseudo-attributes | version first and mandatory, then an optional encoding, then an optional standalone, in that order and no other. The encoding value is a claim about the bytes, not a fact about them; a parser that trusts it will abort on the first byte that contradicts it, and it will abort a long way from wherever the mistake was made. |
| 0 | 5 | DOCTYPE opener | 3C 21 44 4F 43, and at offset 0 only when there is no declaration, no mark and no leading whitespace. Otherwise it is wherever the prolog happens to end - which is the honest answer, and the reason a byte-offset table is the wrong instrument for finding it and a parser is the right one. |
Telling it apart from its neighbours
| Easily confused with | How to tell |
|---|---|
| HTML | Both are angle brackets and neither has a magic number, but the sniffing rules browsers follow separate them cleanly. XML matches the exact bytes 3C 3F 78 6D 6C after optional whitespace; HTML matches a table of tag-name patterns - DOCTYPE HTML, HTML, HEAD, SCRIPT, IFRAME, TITLE, BODY and a dozen more - each of which must be followed by a space or a closing angle bracket to count. The deeper difference is what happens when the document is wrong: an XML parser stops, and an HTML parser recovers. |
| SVG | An SVG is XML. There is no byte that separates them, at offset 0 or anywhere else; the difference is only that the root element is named svg and carries the SVG namespace. A tool that reports svg for a file and a tool that reports xml for the same file are both correct, and any detector that has to choose one is making an editorial decision rather than a technical one. |
| Android binary XML | The AndroidManifest.xml inside an APK is not text at all. It is a chunked binary encoding whose first four bytes are 03 00 08 00 - a little-endian chunk type of 3 and a header size of 8 - followed by the document length. Opening it in a text editor shows binary noise, because every string in the document has been moved into a pool elsewhere in the file and the elements refer to them by index. |
| Word document (docx) | The XML people are looking for inside an Office file is real, but the file on disk begins 50 4B 03 04, because it is a ZIP. Nothing at the front of a .docx, .xlsx or .pptx is XML; the parts are entries inside the archive, and one of them, named [Content_Types].xml, is what makes the package an Office document rather than an arbitrary ZIP that happens to contain markup. |
How these files break
- Junk in the prolog. XML permits a byte-order mark before the declaration and nothing else, so a blank line, a warning printed by a script, or an HTML error page in front of the content produces the error every XML developer has seen: content is not allowed in prolog. It always means exactly one thing - something is in front of the first angle bracket - and a hex viewer finds it in seconds.
- An encoding that lies. The declaration says UTF-8 and the bytes are Windows-1252, or the reverse. Everything parses until the first character above 0x7F, at which point the parser reports an invalid byte sequence and points at a line that looks entirely ordinary on screen, because the offending character renders fine in the editor that wrote it.
- Truncation. XML has no length field and no trailer, so nothing about a document cut short is detectable until the parser runs out of input with elements still open. The message is a premature end of data, and how much is missing cannot be recovered from the file itself at all.
- Control characters in exported data. XML 1.0 permits only tab, line feed and carriage return out of the C0 range and forbids the rest even when they are written as numeric character references. A database export carrying a 0x00 or a 0x0B therefore produces a file that looks well-formed, survives a visual check, and no conforming parser anywhere will accept.
- Unescaped ampersands and angle brackets. Markup assembled by string concatenation rather than by a serialiser breaks the moment a value contains an & or a <. The parser reports an entity reference expecting a semicolon at a position that is inside the data rather than inside the markup, which is why the fix is almost never where the error points.
Where the format stands today
XML has lost most of the ground it held in 2005 and kept the ground that actually mattered. For web APIs and configuration it was replaced by JSON and then by YAML and TOML, and SOAP is legacy nearly everywhere it still runs. What it kept is documents: anything with mixed content, where text and markup interleave and order matters, is far better served by XML than by a data format, and that is why Office, ODF, EPUB, DocBook and TTML subtitles have not moved and are not going to. It also kept the places where validation is the point, since XML Schema, XPath and XSLT have no real equivalent on the JSON side - so a format that must be checked against a contract before it is processed, whether that is a government filing, an invoice, a feed or an Android layout, usually still arrives as XML. As a thing to open in a hex editor it is unusual for having no header whatsoever: the first byte of the file is already content.
Open XML files on this site
Every one of these runs in your browser — the file never leaves your machine.
Related formats
Formats that are easy to confuse with XML — compare their leading bytes.