Choosing XML Over the Alternatives or Not for a New Project
A decision guide for XML versus JSON, YAML, CSV and Protocol Buffers, with measured sizes and parse times, six scenarios and a migration path.

Every few years the question comes back: should this be XML? Teams answer it from habit, from fashion or from whoever is loudest in the meeting. The answer that holds up is dull and specific. It depends on the shape of the content, on who has to read and write it, on what contract the data lives under and on what tools the people involved already have. This guide turns that into a procedure, backs the measurable parts with numbers from one set of tests, and walks through six scenarios so you can see the reasoning applied.
The question behind the question
"XML or JSON?" is rarely the real question. The real questions are underneath it.
What is the content? Records, documents, configuration, a table, a stream of messages? The shape comes first, because some formats cannot express some shapes. Prose with inline markup is a document; an order with lines is a record with nesting; a price list is a table.
Who and what touches it? A human with a text editor, a program you wrote, a partner's integration platform, a regulator's validator. The format must suit the weakest tool in the chain.
What contract governs it? A standard, a partner agreement, a public API, or nothing. Where a contract exists, it usually names the format, and the decision is already made.
How long does it live? A message that lasts a second and a record kept for twenty years have different requirements for self-description and tooling.
What does it cost to change your mind? Once partners depend on a format, switching is a project. Choosing carefully at the start is cheap compared with migrating later.
Size and speed come after these. They matter, and the measurements below show how much, but they rarely decide.
What the formats cost: measured
Here is one realistic message, an order with a customer, a date and one to five lines, serialized 50,000 times in each format:
format bytes gzip
XML 14169433 1812278
JSON 10817478 1738086
YAML 11418224 1769046
protobuf 5068788 1642380
parse ms (best of 3), 50,000 orders:
XML lxml 161
JSON json 132
YAML CLoader 7238
protobuf 9Read it in three passes.
Uncompressed size. Protobuf is about a third of XML. JSON and YAML sit between. XML pays for writing every name twice. If bytes in memory or on disk matter, the order is protobuf, JSON, YAML, XML.
Compressed size. The four are within 10 percent: 1.64 MB for protobuf, 1.81 MB for XML. Repeated names compress away. On a network that compresses, which is nearly every HTTP deployment, size is a weak argument against XML. XML versus Protocol Buffers for services covers the comparison in detail.
Parse time. Protobuf parsed in 9 ms, JSON in 132, XML in 161 and YAML in over 7 seconds. The spread between XML and JSON is small. Protobuf is an order of magnitude faster, which matters at volume. YAML is a configuration format and should not carry bulk data; this is the reason.
For a flat table the picture changes. A table of 100,000 rows and four columns was 3.8 MB as CSV and 10.2 MB as XML, a ratio of 2.7, and 1.04 MB and 1.20 MB after gzip (XML versus CSV for exchanging tabular data). CSV is the lightest on parse time and loader support for data that really is a table.
For configuration, the same five settings took 96 bytes as JSON, 114 as YAML and 215 as XML. Nobody has ever lost anything to 119 bytes. The properties that matter are comments, strictness and quoting: JSON has no comments, YAML turned the unquoted country code NO into False, and XML returned every value as text (XML versus JSON versus YAML for configuration).
The decision procedure
Work down this list. Stop at the first line that applies.
Is the format mandated? A partner contract, a regulator or a platform names it. Use it. Spend your effort on a tolerant reader and validated output.
Is the content a document with inline markup? Paragraphs with emphasis, links, footnotes, code. Choose a document format, which means XML (DocBook, DITA, JATS, TEI, XHTML) or Markdown if the audience is writers and the tooling is yours.
Is it a flat, uniform table? Choose CSV, or Parquet if it is large and analytical. XML adds ceremony and no information.
Does it need signatures or a validated long-term archive? XML with a published schema has the strongest standard tooling for both.
Is it configuration edited by hand? Choose YAML or TOML with a schema; choose XML if the ecosystem (Maven, .NET project files) already does.
Is it a high-volume call between services you control? Choose Protocol Buffers or another schema-first binary format.
Otherwise, choose JSON. It is the default for application data and public APIs for good reasons: small enough, universal tooling, native in browsers.
The order matters. A mandate beats a preference, and a document beats a record, because a document cannot be flattened without loss. If you reach line 7, you were never in XML's territory.
What XML does that the others do not
The case for XML is a short list of capabilities that hold up under inspection.
Inline markup. An element can contain text and elements mixed. With a ten-line XSLT, a paragraph of <cmd> and <emph> elements became HTML, and one XPath call returned the plain sentence. No record format does that without inventing a document model (when XML is still the right format goes through the example).
Standards for contracts. XSD and RELAX NG validate documents with decades of tooling. Industries publish vocabularies in them: e-invoicing, derivatives, health records, financial reporting, publishing.
Signatures and canonicalization. Signing structured documents so they survive parsing and re-serialization is a solved problem in XML (canonical XML and why diffs need it).
Namespaces and extension. Different parties can add vocabulary to one document without collisions (using XML namespaces for extensions).
Self-description. An XML file carries its names and encoding. It can be opened by a stranger. That helps archives and debugging.
Mature transformation and query. XSLT, XPath and XQuery are standardized, implemented everywhere, and unmatched for reshaping documents declaratively.
If you need none of these, the premium XML charges, in ceremony and in unfamiliarity for your developers, buys nothing.
What XML costs
Be as honest about the downsides.
Ceremony. Namespaces, declarations, entities and the attribute-or-element question take effort the others do not ask. Teams that use XML casually produce inconsistent documents (designing XML documents that age well).
Memory when parsed as a tree. A DOM costs ten to fifteen times the file size, which turns large files into a streaming exercise (how much memory a DOM parser needs).
Security surface. Entity expansion and external entities have caused real vulnerabilities, and parsers must be configured safely (XML external entity attacks). JSON has fewer such hazards, though not none.
Developer familiarity. Many developers have never written an XPath. A format your team does not know costs time in every task, and that cost is real even if it never shows in a benchmark.
Lists and types are implicit. XML text has no types and no list type. Every conversion to a typed language needs rules (modeling lists and optional data in XML).
Six scenarios
1. A public REST API for a new product. No mandate, no documents, consumers are web and mobile developers. Line 7: JSON. Add an OpenAPI description and JSON Schema. XML would add cost and would not be requested.
2. A product catalog feed to shopping platforms. Each platform defines its own format, most of them XML (Google Merchant, others offer CSV too). Line 1: use what the platform requires. Generate from one model and render per platform, and validate your output before upload.
3. Technical documentation for software. The content is prose with code spans, admonitions and cross references. Line 2: a document format. DocBook or DITA if you need conditional text and large-scale reuse, Markdown if you do not. Do not store it as JSON blocks and invent a renderer.
4. Nightly export of orders to a data warehouse. Rows with lines, a few million per night. Both ends are yours. XML would work and would cost memory and a mapping layer. Prefer CSV or Parquet for tables, or JSON lines for nested records (choosing Parquet after you parse XML). Use XML only if the source system emits nothing else, and then parse it by streaming (parsing big XML files fast).
5. Application settings for an internal service. Edited by operators, read by a Python service. Line 5: YAML with a schema and strict quoting, or TOML. The Norway problem is a reason to validate, not to switch to XML.
6. A signed invoice exchanged with customers in several countries. Governed by national e-invoicing rules that specify an XML vocabulary and a signature scheme. Line 1 and line 4: XML, and the work is conformance.
Notice how rarely size or speed appeared in the reasoning. Scenario 4 is the one place where they did, and even there the format choice came mainly from the shape of the data.
A scoring worksheet
When the procedure above leaves two formats standing, a worksheet makes the argument concrete. List the factors that apply, give each a weight from one to five for how much it matters to this project, and score each format from zero to three for how well it serves that factor. Multiply, add up and look at the gap. The number is not the point. The point is that the weights force the team to say what matters, and the scores force them to defend a claim about a format with a fact.
Typical factors, with the reasoning that usually applies:
Fit for the content shape. Mixed content scores high for XML and low for everything else. Flat tables score high for CSV.
Tooling the team already has. If every developer reads JSON in their sleep and nobody has written XSLT, that is a cost on one side. Count it.
Validation and contracts. XML Schema, JSON Schema and protobuf's compiler each give a different kind of guarantee. A contract with an outside party that names one wins.
Readability by people. Text formats beat binary for anything that gets debugged by hand or reviewed in a pull request.
Parse cost at your volume. Multiply your message rate by the parse times above before you call it a factor. At a hundred messages a second, no format here is a problem. At a hundred thousand, protobuf may be the only one that fits.
Evolution. How easily can you add a field without breaking readers? Protobuf and XML with an extension point both handle it with discipline, JSON by convention.
Longevity. Will anyone need to read this in ten years without the original software?
Two warnings about the worksheet. First, do not let the weights be set after the scores are known, because people adjust them to reach the answer they came in with. Second, put an honest "unknown" in the scores where nobody has data, and go and get the data: a one-hour benchmark on real messages replaces a lot of opinions.
Formats by field
Industries settle into formats for reasons that outlast fashion, and knowing the convention in yours saves arguments.
Publishing and documentation. XML dominates where content is reused and typeset: journal articles in JATS, technical manuals in DITA and DocBook, humanities texts in TEI. Lightweight alternatives like Markdown win for developer documentation where the audience is the author.
Finance and insurance. ISO 20022 payment messages, FpML, XBRL reports and many regulatory submissions are XML with schemas and signatures. Internal trading systems often use binary formats for speed, and translate at the boundary.
Health. HL7 v3 and CDA documents are XML; FHIR offers both XML and JSON representations of the same resources, which is a good example of the dual-rendering approach in practice (keeping both XML and JSON output from one source).
Government and open data. Statistical agencies and legislatures publish in XML, CSV and JSON side by side, often with the CSV as the entry point for analysts.
Web and mobile products. JSON for APIs, with Protocol Buffers or similar between internal services. XML shows up in feeds (RSS, Atom, sitemaps), in SVG and in integrations with older enterprise systems.
Data engineering. CSV, JSON lines and Parquet. XML is something to be parsed and landed, and the best practice is to convert once, early, to a columnar format.
If your field has a convention, follow it unless you have a measured reason not to. Your counterpart's tooling was built around it.
XML at the edge, something else inside
A pattern that resolves many arguments is to use different formats in different places. At the boundary with outside parties you speak whatever they require, and inside you use what suits your own systems. The boundary is a service, a library or a module with one job: parse and validate incoming documents, map them to your internal model, and render outgoing documents from the model.
This isolates the awkward parts. XML namespaces, entity handling and schema versions live in the adapter, and the rest of the code sees plain objects. When the partner changes their vocabulary, you change the adapter. When you decide to adopt a different internal encoding, the adapter does not care.
It also gives you one place to apply the defenses that XML needs. Parsers configured to refuse external entities and DTDs, limits on document size and nesting depth, a streaming path for big files and a validation step against the partner's schema all belong in the adapter (safe XML parsing in Python with defusedxml shows the configuration). Put them there once and every integration inherits them.
The cost is a mapping to write and test. Budget for it, and test with the awkward cases: lists of one, empty and absent values, special characters, long text, non-ASCII names. The corpus approach pays for itself here.
Pitfalls when data crosses formats
Whatever you choose, data usually crosses a boundary between formats, and a few things go wrong at every crossing.
Numbers. JSON has one number type, usually read as a double. A 64-bit identifier or an amount with many decimals loses precision in a JavaScript client. XML and CSV carry text and say nothing about precision. Send identifiers and money as strings, and parse them with a decimal type.
Dates and time zones. Use ISO 8601 with an explicit offset or Z. A bare 2026-03-14 10:00 is ambiguous in every format, and silently becomes someone's local time.
Null, absent and empty. XML has three states, JSON has null and absent, CSV has an empty cell. A round trip through CSV collapses all of them. Decide what each means and write it down.
Ordering. XML element order is significant, and JSON object order is not guaranteed by the standard. If order matters in JSON, use an array.
Whitespace and Unicode. XML attribute values normalize whitespace, CSV preserves it inside quotes, and JSON preserves everything in strings. Text normalized differently in two systems, for instance an accented letter as one character or as two, compares unequal (how CSV quoting works shows one of the neighboring problems).
Identifiers with leading zeros. 00123 is a string. Any format that guesses types, from a spreadsheet to a YAML parser, may turn it into a number.
Each of these is cheap to handle once and expensive to find in production. The corpus test, with one case per hazard, finds them while the cost is a failing test.
A one-hour bake-off
When the formats are close and the volume is real, measure instead of arguing. The experiment needs real messages, a script and an hour.
Take a sample of actual data: a few thousand messages with their natural variety, not one tidy example. Write one function that loads the sample into plain objects. Then serialize the set into each candidate format, and record four things: bytes uncompressed, bytes gzipped, time to serialize and time to parse, each as the best of several runs so a cold cache does not decide the result. The tests above are a template: the XML tree built with lxml, json.dumps with compact separators, yaml.safe_dump, and a protobuf message generated from a short schema, all from the same list of dictionaries.
Add two checks that are not about speed. Round-trip every message and compare it with the original, which finds the formats that lose information (dates as strings, empty versus null, integers beyond 53 bits). And write the three ugliest messages you can think of, with markup characters, non-ASCII names, an empty list and a missing field, and look at what each format does to them.
Then read the results with your own threshold in mind. If the formats differ by less than your measurement noise, or by less than the cost of a second code path, the choice should go to the one your team and partners know. If one is ten times faster at your volume, that is a real signal, and you should ask what it costs elsewhere. Keep the script. It becomes the regression benchmark when the data changes shape.
Questions for a partner who asks for XML
Sometimes the format is decided by the other side, and the useful work is to learn what "XML" means to them. A short list of questions turns a vague request into a specification.
Is there a schema, and which one? An XSD, a DTD or a published vocabulary. If the answer is "we will send you a sample", ask for the schema anyway, and offer to infer one from samples and send it back for confirmation.
Which namespace and version? A document with the wrong namespace fails in surprising ways.
What encoding? UTF-8 is the answer you want. Anything else needs a declaration and a test.
How are empty and missing values represented? Elements absent, empty or nil.
How big can a document be, and how many per hour? This decides streaming and limits.
Is the whole document signed, or parts of it? Signing changes what you may do with whitespace and ordering.
How are errors reported? A response document, an HTTP status, an email. A good answer names the element and the reason.
Is there a test environment and sample documents? The real specification is often the example files.
Write the answers down and send them back as the interface document. It is also the first test plan: one document for each answer.
Changing your mind later
Few decisions are final. If you chose XML and it turns out to be wrong, or the reverse, the migration is a project with a known shape: freeze the contract, define the new mapping explicitly, serve both formats from one model, test parity on a corpus, measure who calls which, announce a date and retire (migrating a legacy XML interface to JSON and keeping both XML and JSON output from one source). The cost of the migration is dominated by consumers, not by code, which is a reason to take the first choice seriously and not to treat migration as free insurance.
A way to keep the door open is to separate the model from the format from the start. If the application works with objects and renders them at the edge, switching a rendering is a bounded change. If XML structures leak through the code, as element names in business logic and XPath expressions in controllers, every change is tangled up with it.
Related reading
The sibling posts in this cluster: XML versus JSON versus YAML for configuration, XML versus CSV for exchanging tabular data, XML versus Protocol Buffers for services and when XML is still the right format. For the cross-format basics, see XML versus JSON for data exchange. Moving data between them is covered in converting between XML, JSON, CSV and YAML.
Primary sources: the XML 1.0 specification, RFC 8259 for JSON, the YAML 1.2.2 specification, RFC 4180 for CSV and the Protocol Buffers documentation. Convert and compare a snippet in the XML to JSON tool and the YAML to JSON tool.
When this decision guide does not apply
You have no choice. The decision belongs to somebody else. Implement their format well.
The decision is small. A script that passes data between two programs of yours for a month does not warrant a procedure. Use the easiest format and move on.
The data is very large and analytical. At warehouse scale the question is not XML versus JSON but row versus columnar storage. Convert once to Parquet and query with an engine built for it.
Your constraints differ from these tests. The measurements are for Python on one dataset. A language with a fast XML parser, or a payload of long text, changes the ratios. Re-run the comparison on your own messages before putting a number in a design document.
Taste is the actual reason. If the team prefers a format and nothing contradicts it, that preference has value: people write better in tools they like. Be honest that it is a preference, and choose it knowingly.


