PHP XML Parsers
What Is XML? In simple terms: XML (eXtensible Markup Language) is a text format for structured data, written with tags similar to HTML. Unlike HTML, the tags are not predefined — you invent names that
What Is XML?
In simple terms: XML (eXtensible Markup Language) is a text format for structured data, written with tags similar to HTML. Unlike HTML, the tags are not predefined — you invent names that describe your data: <product>, <price>, <invoice>. Many systems exchange data as XML: RSS and Atom news feeds, sitemaps for search engines, SOAP web services, e-invoicing standards, bank statements, and Microsoft Office files (which are ZIP archives of XML documents).
Technically: An XML document is a tree of elements. Elements can have attributes, text content, and child elements. Documents must be well-formed: exactly one root element, every opening tag closed, tags properly nested, attribute values quoted, and special characters escaped (<, >, &). Namespaces (xmlns) distinguish elements from different vocabularies.
The Example Document Used in This Section
<?xml version="1.0" encoding="UTF-8"?>
<catalog store="GoCourse Shop" updated="2026-10-15">
<product sku="PEN-01" category="stationery">
<name>Gel Pen</name>
<price currency="INR">20.00</price>
<stock>120</stock>
</product>
<product sku="LAMP-01" category="electronics">
<name>Desk Lamp</name>
<price currency="INR">1299.00</price>
<stock>6</stock>
</product>
<product sku="MOUSE-01" category="electronics">
<name>Wireless Mouse</name>
<price currency="INR">599.00</price>
<stock>30</stock>
</product>
</catalog>
| Part | Example |
|---|---|
| XML declaration | <?xml version="1.0" encoding="UTF-8"?> |
| Root element | <catalog> |
| Attribute | sku="PEN-01" |
| Child element with text | <name>Gel Pen</name> |
The following lessons assume this document is stored in the variable $catalogXml (or the file catalog.xml).
PHP's XML Tools
PHP offers several XML extensions, which fall into two families:
| Tool | Type | Reads Whole Document Into Memory? | Best For |
|---|---|---|---|
| SimpleXML | Tree-based | Yes | Quick, readable access to small and medium documents |
DOM (DOMDocument, PHP 8.4 Dom\XMLDocument) | Tree-based | Yes | Full control: editing, XPath, creating documents, HTML |
| XML Parser (Expat) | Event-based (push) | No | Streaming large files with callbacks |
| XMLReader | Stream-based (pull) | No | Streaming large files with a cursor; combinable with DOM/SimpleXML |
| XMLWriter | Writer | No | Generating large XML documents efficiently |
Tree-Based vs Stream-Based
Tree-based (SimpleXML, DOM): Stream-based (XMLReader, Expat):
read whole file → build tree in memory read → handle element → forget → next element
→ navigate freely, modify, save → constant memory, forward-only
- Tree-based parsers are convenient: you can jump to any element, search with XPath, and modify the document. Memory use grows with the document size — often several times the file size.
- Stream-based parsers read the document piece by piece. They handle gigabyte-sized files with constant memory but only move forward.
A common rule: use SimpleXML or DOM for documents up to a few megabytes; use XMLReader for large feeds and exports.
A First Taste
<?php
$catalog = simplexml_load_string($catalogXml);
echo "Store: {$catalog['store']}\n";
echo "Products: " . count($catalog->product) . "\n";
echo "First product: {$catalog->product[0]->name}\n";
Output
Store: GoCourse Shop
Products: 3
First product: Gel Pen
SimpleXML maps elements to object properties and attributes to array keys — the details follow in PHP SimpleXML Parser.
Handling Invalid XML
XML from external sources may be malformed. By default, libxml (the library behind SimpleXML and DOM) reports problems as PHP warnings. Collecting them instead allows proper error handling:
<?php
libxml_use_internal_errors(true);
$document = simplexml_load_string('<catalog><product></catalog>');
if ($document === false) {
$error = libxml_get_errors()[0];
echo "Invalid XML at line {$error->line}: " . trim($error->message) . "\n";
libxml_clear_errors();
}
Output
Invalid XML at line 1: Opening and ending tag mismatch: product line 1 and catalog
libxml_use_internal_errors(true)stores errors instead of emitting warnings.simplexml_load_string()returnsfalsefor documents that are not well-formed.libxml_get_errors()returnsLibXMLErrorobjects with the message, line, column, and severity.libxml_clear_errors()empties the error buffer before the next parse.
Security: XML External Entities (XXE)
XML can define entities, including external entities that load content from files or URLs. A malicious document could use them to read files from your server (file:///etc/passwd) or make the server send requests (XXE attacks).
| Situation | Safe? |
|---|---|
| Default settings with libxml 2.9+ (all supported PHP versions) | External entities are not loaded |
Passing LIBXML_NOENT (substitute entities) or LIBXML_DTDLOAD for untrusted input | Dangerous — re-enables entity expansion/loading |
libxml_disable_entity_loader() | Deprecated since PHP 8.0; no longer needed |
Rules for untrusted XML:
- Do not pass
LIBXML_NOENT,LIBXML_DTDLOAD, orLIBXML_DTDATTRwhen parsing external documents. - Limit the size of uploaded or downloaded XML.
- Treat values extracted from XML like any other input: validate them and escape them on output.
Choosing the Right Parser
| Task | Recommended |
|---|---|
| Read a configuration file or API response | SimpleXML |
| Find elements with complex conditions | SimpleXML or DOM with XPath |
| Modify or create documents | DOM (or SimpleXML for simple changes) |
| Parse HTML pages | DOM — in PHP 8.4, Dom\HTMLDocument |
| Import a 2 GB product feed | XMLReader (expanding each record with SimpleXML/DOM) |
| Generate a large sitemap or export | XMLWriter |
| Legacy code with event callbacks | XML Parser (Expat) |
XML or JSON?
For new APIs between your own systems, JSON is usually simpler (see PHP JSON). XML remains important where standards require it: feeds, sitemaps, SOAP services, government and banking formats, and document formats.
Common Mistakes
Parsing Large Files With Tree-Based Parsers
Effect: Memory exhaustion.
Fix: Use XMLReader for large documents.
Ignoring Parse Errors
Effect: false is used as a document, leading to confusing errors later.
Fix: Check the return value and collect libxml errors.
Enabling Entity Substitution for Untrusted Input
Effect: XXE vulnerabilities.
Fix: Keep default options; never use LIBXML_NOENT with external XML.
Building XML With String Concatenation
Effect: Unescaped & or < in values produce invalid XML.
Fix: Use SimpleXML, DOM, or XMLWriter to generate XML.
Best Practices
- Choose tree-based parsers for convenience and stream-based parsers for size.
- Always check whether parsing succeeded and handle errors.
- Keep libxml's secure defaults for untrusted documents.
- Use XPath for searching instead of manual nested loops.
- Generate XML with an XML API, never by concatenating strings.
Official reference: https://www.php.net/manual/en/refs.xml.php