XML
The W3C’s markup language for trees of tagged text, still behind Office documents, SVG, feeds, SOAP and the S3 API.
- What it is
- File formats (text and markup)
- Type
- Open source
- Made by
- W3C (open standard)
- License
- Open standard, free to implement (W3C Recommendation)
- Facts checked
- 6 October 2026
What it is
An XML document is a tree of elements. Each element has a start and end tag (<order id="42">…</order>, or <empty/>), and may hold attributes, text, other elements, comments (<!-- -->) and CDATA sections. A document must be well-formed: one root element, properly nested tags, quoted attribute values. When a parser finds a well-formedness error, the spec says it must stop passing data to the application. Everything is text: XML itself has no numbers or dates, and types come from a schema. An optional document type declaration (DTD) describes the allowed structure and defines entities, named pieces of replacement text, including external entities that point at a file or URL. Namespaces qualify element names with a URI, so vocabularies such as SVG can be mixed into other documents without name clashes.
The core spec is a W3C Recommendation, XML 1.0, now in its Fifth Edition (November 2008), and free to implement. Around it sit W3C XML Schema (XSD 1.1, 2012) for structure and data types, RELAX NG (ISO/IEC 19757-2) as a simpler schema language, and XPath 3.1 (2017) for selecting nodes. XML still defines Office Open XML documents (ECMA-376), SVG, RSS and Atom feeds and SOAP messages. Amazon S3’s REST API answers in XML, and Azure Blob Storage’s List Blobs returns XML unless a client asks for its newer Apache Arrow format.
Why teams pick it
- Mature standards for validation (DTD, XSD, RELAX NG) and querying (XPath), so documents can be checked strictly
- Mixed content (text with markup inside it) suits documents such as Office files and SVG
- Namespaces let one document combine vocabularies from different owners without clashing names
- Strict well-formedness: a broken document is rejected instead of being guessed at
Watch out for
- Verbose by design: the spec says terseness “is of minimal importance”, and every end tag repeats its name
- No data types without a schema; every value arrives as text and the application converts it
- Unsafe parser defaults: resolving DTDs and external entities opens the door to XXE (reading local files, server-side request forgery) and “billion laughs” entity-expansion attacks; OWASP’s advice is to disable DTDs entirely
- Namespaces trip up code: S3 puts every element of its responses in a default namespace, so unqualified lookups find nothing
Alternatives
What all text and markup have in common →How it fits with other technologies
Parsing an S3 ListObjectsV2 response: mind the default namespace · python
import xml.etree.ElementTree as ET # Expat underneath; doesn't fetch external entities by default
body = """<?xml version="1.0" encoding="UTF-8"?>
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Name>amzn-s3-demo-bucket</Name>
<Prefix>logs/</Prefix>
<KeyCount>2</KeyCount>
<MaxKeys>1000</MaxKeys>
<IsTruncated>false</IsTruncated>
<Contents>
<Key>logs/2026-10-05.jsonl.gz</Key>
<Size>857</Size>
</Contents>
<Contents>
<Key>logs/2026-10-06.jsonl.gz</Key>
<Size>1204</Size>
</Contents>
</ListBucketResult>"""
root = ET.fromstring(body)
print(root.findall("Contents")) # [] : unqualified names match nothing
ns = {"s3": "http://s3.amazonaws.com/doc/2006-03-01/"}
for obj in root.findall("s3:Contents", ns):
key = obj.findtext("s3:Key", namespaces=ns)
size = int(obj.findtext("s3:Size", namespaces=ns)) # everything is text
print(key, size)
# logs/2026-10-05.jsonl.gz 857
# logs/2026-10-06.jsonl.gz 1204JSON, YAML, TOML and XML side by side#
Four text formats for structured data. They overlap, but each grew up around a different job, and that shows in what they leave out.
| JSON | YAML | TOML | XML | |
|---|---|---|---|---|
| Current spec | RFC 8259 and ECMA-404 (both December 2017) | YAML 1.2.2 (October 2021), a revision of 1.2 from 2009 | TOML 1.1.0 (December 2025) | W3C XML 1.0, Fifth Edition (November 2008) |
| Comments | None | # to the end of the line | # to the end of the line | <!-- … --> |
| Built-in value types | String, number, boolean, null | Null, boolean, integer, float and string in the recommended core schema; others through tags | String, integer, float, boolean, offset and local date-times, dates and times | None: content is text until a schema gives it types |
| Nesting | Objects and arrays | Mappings and sequences; anchors and aliases reuse a node | Tables, arrays, inline tables and arrays of tables | Elements with attributes; namespaces mix vocabularies |
| Schema language | JSON Schema, a separate spec (latest 2020-12) | None; the spec’s “schemas” only decide how unquoted values are typed | None in the spec | DTDs (part of XML 1.0), W3C XML Schema (XSD), RELAX NG |
| Typical use | Web API bodies; JSON Lines logs and events | Kubernetes manifests, GitHub Actions workflows, Compose files | Cargo.toml, pyproject.toml, Telegraf config | Office documents, SVG, RSS and Atom feeds, SOAP, the S3 API |
- Each cell is taken from the format’s own specification, and typical uses from the documentation of the tools named. The same table appears on the JSON, YAML, TOML and XML pages.
See it in a real stack
No architecture uses XML yet. Drop it into the playground and wire it up yourself.Open playground →Where it came from1996–2008
The Web of the mid-1990s served HTML, one fixed set of tags. SGML, the general markup standard, let anyone define their own tags, but its documents couldn’t be served on the Web the same way. In 1996 the W3C formed a working group, at first called the SGML Editorial Review Board and chaired by Jon Bosak of Sun Microsystems, to let “generic SGML” be served, received and processed on the Web the way HTML was. Its answer was a subset of SGML small enough to be described completely in one spec. Edited by Tim Bray, Jean Paoli and C. M. Sperberg-McQueen, XML 1.0 became a W3C Recommendation on 10 February 1998.
A family of standards grew around it: Namespaces in 1999, W3C XML Schema in 2001, and formats built on XML such as SOAP, RSS, Atom (2005) and Office Open XML (2006). In December 2006, Douglas Crockford pitched JSON to the XML 2006 conference as “the fat-free alternative to XML” for data exchange in browsers. The Fifth Edition of XML 1.0, published in November 2008, is still the current text.
Why it’s built this way
- A subset of SGML
- Compatibility with SGML was a design goal, so SGML tools could still process XML documents, while another goal kept XML easy to write programs for.
- Errors are fatal
- The goals asked for programs that are easy to write and for optional features to be kept to “the absolute minimum, ideally zero”. A processor that hits a well-formedness error must stop normal processing, so parsers don’t each invent their own recovery.
- Terseness is of minimal importance
- An explicit design goal. Clarity and easy processing beat compactness, which is why every end tag repeats its element’s name.
- Namespaces as URIs, added a year later
- Mixing vocabularies needed globally unique names. The 1999 Namespaces spec qualified names with URIs, often written as web addresses, without changing XML 1.0 itself.
Timeline
- 1996
W3C forms the SGML Editorial Review Board, chaired by Jon Bosak
- 1998
XML 1.0 becomes a W3C Recommendation (10 February)
- 1999
Namespaces in XML (January)
- 2001
W3C XML Schema 1.0 (May)
- 2005
Atom syndication format published as RFC 4287
- 2006
ECMA-376 standardises Office Open XML (December)
- 2008
XML 1.0 Fifth Edition, the current text (November)
- W3C: XML 1.0 Fifth Edition, 1.1 Origin and Goals
- W3C: Extensible Markup Language (XML) 1.0, Recommendation of 10 February 1998
- W3C: Namespaces in XML, Recommendation of 14 January 1999
- W3C: XML Schema Part 1: Structures, Recommendation of 2 May 2001
- RFC 4287: The Atom Syndication Format (December 2005)
- ECMA-376 page: 1st edition, December 2006
- Douglas Crockford: JSON, The Fat-Free Alternative to XML (XML 2006)
Sources29 · facts checked 6 October 2026
- W3C: Extensible Markup Language (XML) 1.0, Fifth Edition (26 November 2008)
- W3C: Namespaces in XML 1.0, Third Edition (December 2009)
- W3C XML Schema Definition Language (XSD) 1.1 Part 1: Structures (April 2012)
- W3C XML Schema Definition Language (XSD) 1.1 Part 2: Datatypes (April 2012)
- RELAX NG home page (ISO/IEC 19757-2)
- W3C: XML Path Language (XPath) 3.1 (March 2017)
- ECMA-376: Office Open XML file formats
- W3C: Scalable Vector Graphics (SVG) 2, a language based on XML
- RSS Advisory Board: RSS 2.0 specification (RSS is a dialect of XML)
- RFC 4287: The Atom Syndication Format (December 2005)
- W3C: SOAP Version 1.2 Part 1: Messaging Framework (Second Edition)
- Amazon S3 API Reference: ListObjectsV2 (XML response)
- Azure Storage REST API: List Blobs (XML by default; Arrow from version 2026-06-06)
- OWASP: XML External Entity Prevention Cheat Sheet (disable DTDs)
- OWASP: XML Security Cheat Sheet (billion laughs, quadratic blowup)
- Python docs: XML processing modules and their vulnerabilities (Expat defaults)
- RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format (December 2017)
- ECMA-404: The JSON data interchange syntax, 2nd edition (December 2017)
- JSON Schema: Specification (latest meta-schema 2020-12)
- JSON Lines: text format, also called newline-delimited JSON
- YAML Ain’t Markup Language, revision 1.2.2 (October 2021)
- Kubernetes docs: Objects in Kubernetes (manifests are YAML by convention)
- GitHub Docs: Workflow syntax for GitHub Actions (workflow files use YAML)
- Docker Docs: Compose file reference
- TOML v1.1.0 specification
- toml-lang/toml: 1.1.0 release notes (24 December 2025)
- The Cargo Book: The manifest format (`Cargo.toml` is written in TOML)
- Python Packaging User Guide: `pyproject.toml` specification
- Telegraf docs: Configure Telegraf (a TOML configuration file)