XML Parsing and Transformation: A Developer's Guide
Learn the fundamentals of XML parsing with DOM and SAX approaches, XPath queries, XSLT transformations, and how XML compares to JSON for modern development.
XML parsing is the process of reading an XML document and converting its tags and content into a structure — typically a navigable tree or a stream of events — that your code can query and manipulate. XML has been around since 1998, and despite JSON’s dominance in web APIs, you will still encounter it regularly: configuration files, SOAP services, RSS feeds, SVG graphics, Office documents, and countless enterprise systems all rely on XML. Knowing how to parse, query, and transform it is a practical skill that pays off repeatedly.
This guide covers the core parsing strategies, query languages, and transformation tools you need to work with XML confidently.
The Two Parsing Models: DOM vs SAX
When you parse an XML document, you have two fundamental approaches. Each one makes different tradeoffs between memory usage, speed, and convenience.
DOM Parsing
DOM (Document Object Model) parsing reads the entire XML document into memory and builds a tree structure. You can then navigate, search, and modify that tree however you want.
const parser = new DOMParser();
const doc = parser.parseFromString(xmlString, "text/xml");
// Navigate the tree
const items = doc.querySelectorAll("item");
items.forEach(item => {
const title = item.querySelector("title").textContent;
console.log(title);
});
When to use DOM parsing:
- The document fits comfortably in memory (under a few hundred MB)
- You need random access to different parts of the document
- You want to modify the document and serialize it back
- You need to run multiple queries against the same document
Downsides:
- Memory usage scales linearly with document size
- Parsing the entire document takes time before you can access any data
- A 1 GB XML file will consume several GB of RAM as a DOM tree
SAX Parsing
SAX (Simple API for XML) is an event-driven parser. Instead of building a tree, it reads the document sequentially and fires events as it encounters elements, attributes, and text content.
import xml.sax
class ItemHandler(xml.sax.ContentHandler):
def __init__(self):
self.current_element = ""
self.items = []
def startElement(self, name, attrs):
self.current_element = name
def characters(self, content):
if self.current_element == "title":
self.items.append(content)
def endElement(self, name):
self.current_element = ""
handler = ItemHandler()
xml.sax.parse("large-catalog.xml", handler)
When to use SAX parsing:
- The document is very large (hundreds of MB or more)
- You only need to extract specific data, not the whole structure
- Memory is constrained
- You are processing a stream of XML data
Downsides:
- You cannot go backward — it is a single-pass read
- Code is more verbose and harder to reason about
- You must maintain your own state to track context
StAX: The Middle Ground
StAX (Streaming API for XML) is a pull-based parser available in Java and some other languages. Unlike SAX where the parser pushes events to you, with StAX you pull events when you are ready for them. This gives you more control over the parsing flow without loading the whole document into memory.
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(inputStream);
while (reader.hasNext()) {
int event = reader.next();
if (event == XMLStreamReader.START_ELEMENT
&& "title".equals(reader.getLocalName())) {
System.out.println(reader.getElementText());
}
}
XPath: Querying XML Documents
XPath is a query language for selecting nodes from an XML document. If DOM parsing gives you the tree, XPath gives you a way to find specific branches without walking the whole thing manually.
Basic XPath Expressions
| Expression | Meaning |
|---|---|
/catalog/book |
All book elements directly under catalog |
//book |
All book elements anywhere in the document |
//book[@category='fiction'] |
Books with a category attribute of “fiction” |
//book[price > 20] |
Books where the price child element exceeds 20 |
//book[1] |
The first book element |
//book/title/text() |
The text content of all book title elements |
Using XPath in JavaScript
const doc = new DOMParser().parseFromString(xmlString, "text/xml");
// Evaluate an XPath expression
const result = doc.evaluate(
"//book[@category='fiction']/title",
doc,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
for (let i = 0; i < result.snapshotLength; i++) {
console.log(result.snapshotItem(i).textContent);
}
Using XPath in Python
from lxml import etree
tree = etree.parse("catalog.xml")
titles = tree.xpath("//book[@category='fiction']/title/text()")
for title in titles:
print(title)
XPath supports predicates, functions, and axes that make it remarkably powerful. You can select ancestors, siblings, and descendants with precision. For complex XML documents, learning XPath well saves you from writing recursive traversal code by hand.
XSLT: Transforming XML
XSLT (Extensible Stylesheet Language Transformations) transforms XML documents into other formats — different XML structures, HTML, or plain text. It uses templates that match patterns in the source document.
A Simple XSLT Example
Given this XML:
<catalog>
<book>
<title>The Pragmatic Programmer</title>
<author>David Thomas</author>
<price>49.99</price>
</book>
<book>
<title>Clean Code</title>
<author>Robert Martin</author>
<price>39.99</price>
</book>
</catalog>
This XSLT transforms it into an HTML table:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/catalog">
<html>
<body>
<table border="1">
<tr><th>Title</th><th>Author</th><th>Price</th></tr>
<xsl:for-each select="book">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="author"/></td>
<td><xsl:value-of select="price"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
XSLT is especially useful when you receive data in one XML format and need to deliver it in another. Many enterprise integrations rely on XSLT pipelines to bridge systems that use different schemas.
XML vs JSON: When to Use Which
This is not an either-or decision. Both formats have clear strengths.
XML Strengths
- Schemas and validation: XSD provides rigorous type checking and structural validation
- Namespaces: Multiple vocabularies can coexist in one document without conflicts
- Mixed content: Text and markup can be interleaved (essential for documents, not just data)
- Transformation ecosystem: XSLT, XPath, and XQuery are mature and powerful
- Attributes: Metadata can live separately from content
JSON Strengths
- Simplicity: Fewer concepts, less syntax, easier to read
- Native JavaScript support: No parsing step needed in the browser
- Smaller payload: No closing tags means less bandwidth
- Type mapping: Numbers, booleans, arrays, and objects map naturally to programming language types
- API convention: REST APIs overwhelmingly use JSON
Quick Comparison
| Feature | XML | JSON |
|---|---|---|
| Human readability | Moderate | High |
| Verbosity | High | Low |
| Schema validation | XSD, RelaxNG, DTD | JSON Schema |
| Comments | Supported | Not supported |
| Attribute support | Yes | No (use nested objects) |
| Namespace support | Yes | No |
| Browser parsing | DOMParser | JSON.parse |
| Typical use cases | Config, documents, SOAP | APIs, config, data exchange |
Converting Between XML and JSON
In practice, you often need to convert data between formats. An API returns JSON, but a downstream system expects XML — or you are migrating a legacy service that speaks XML to a modern JSON-based architecture.
You can use our JSON to XML converter to quickly transform JSON payloads into well-formed XML. Going the other direction, our XML to JSON converter handles the translation back, including attributes and nested structures.
When converting, watch out for these common issues:
- Attributes vs elements: JSON has no concept of attributes, so converters must decide how to represent them (often with an
@prefix) - Arrays: A single XML child element might be an array or a single value — converters cannot always tell without a schema
- Mixed content: XML elements with both text and child elements do not have a clean JSON equivalent
- Namespaces: Namespace prefixes need special handling during conversion
Practical Tips
-
Validate early: Parse XML with validation against a schema before processing. Our XML formatter can pretty-print and validate a document’s structure in the browser, which makes catching errors early easier before you write processing code.
-
Use XPath over manual traversal: Writing recursive tree-walking code is error-prone. XPath expressions are declarative and much easier to maintain.
-
Stream large files: If your XML file is over 50 MB, use SAX or StAX instead of DOM. The memory savings are significant.
-
Prefer libraries over regex: Never parse XML with regular expressions. XML is not a regular language, and regex will break on edge cases like CDATA sections, namespaces, and nested elements.
-
Handle encoding correctly: XML declares its encoding in the prolog (
<?xml version="1.0" encoding="UTF-8"?>). Respect it, or you will get garbled text for any non-ASCII content.
Wrapping Up
XML parsing is a skill you will use more than you expect, even in a JSON-first world. Understanding the DOM and SAX tradeoffs helps you choose the right tool for the job. XPath saves you from writing tedious traversal code. And knowing when XML genuinely fits better than JSON — or when to convert between the two — makes you a more effective developer.
The format may not be trendy, but it is everywhere, and knowing how to handle it well sets you apart.
Comments