PHP XML Expat Parser
In this page:
$parser = xml_parser_create();
xml_set_element_handler($parser, "start_handler", "end_handler");
xml_parse($parser, $data, true);
xml_parser_free($parser);
Why Use a Streaming Parser
SimpleXML and DOM both load an entire XML document into memory as a tree before you can read anything -- fine for small files, but potentially a serious memory problem for a multi-gigabyte XML export.
Expat instead streams through the document once, processing it piece by piece without ever holding the whole thing in memory.
Example: Why Use a Streaming Parser
<?php
// Print "Expat streams through XML piece by piece instead of loading a full tree into memory" to the output
echo "Expat streams through XML piece by piece instead of loading a full tree into memory";
?>
Login to try C/C++/Java/PHP code in the editor
Creating a Parser and Registering Handlers
xml_parser_create() creates a new parser instance, and xml_set_element_handler($parser, $startCallback, $endCallback) registers two functions: one called every time an opening tag is encountered, and another every time a closing tag is encountered.
Example: Creating a Parser and Registering Handlers
<?php
// Declare `$parser`, set to `xml_parser_create()`
$parser = xml_parser_create();
xml_set_element_handler($parser, function ($parser, $name) {
// Print "Start: $name\n" to the output
echo "Start: $name\n";
}, function ($parser, $name) {
// Print "End: $name\n" to the output
echo "End: $name\n";
});
// Print "Handlers registered" to the output
echo "Handlers registered";
// Call `xml_parser_free($parser)`
xml_parser_free($parser);
?>
Login to try C/C++/Java/PHP code in the editor
Parsing XML Data
xml_parse($parser, $data, $isFinal) feeds a chunk of XML text to the parser, triggering the registered callbacks as it processes that chunk -- passing true as the final $isFinal argument tells the parser this is the last piece of data, letting it detect an incomplete document.
Example: Parsing XML Data
<?php
// Declare `$parser`, set to `xml_parser_create()`
$parser = xml_parser_create();
xml_set_element_handler($parser, function ($p, $name) { echo "<$name>\n"; }, function ($p, $name) { echo "</$name>\n"; });
// Call `xml_parse($parser, "<book><title>PHP</title></book>", true)`
xml_parse($parser, "<book><title>PHP</title></book>", true);
// Call `xml_parser_free($parser)`
xml_parser_free($parser);
?>
Login to try C/C++/Java/PHP code in the editor
Building Data with Handler State
Since each Expat callback only sees the single tag or text chunk it was just given, tracking meaningful state across multiple calls (like which element is currently open, or accumulating a list of parsed records) requires using variables outside the handler functions, often global or captured by reference.
Example: Building Data with Handler State
<?php
// Declare `$titles` as an empty array
$titles = [];
// Declare `$parser`, set to `xml_parser_create()`
$parser = xml_parser_create();
// Call `xml_set_element_handler($parser, function () {}, function () {})`
xml_set_element_handler($parser, function () {}, function () {});
xml_set_character_data_handler($parser, function ($p, $data) use (&$titles) {
if (trim($data) !== '') $titles[] = trim($data);
});
// Call `xml_parse($parser, "<book>PHP Basics</book>", true)`
xml_parse($parser, "<book>PHP Basics</book>", true);
// Print a human-readable dump of `$titles`
print_r($titles);
// Call `xml_parser_free($parser)`
xml_parser_free($parser);
?>
Login to try C/C++/Java/PHP code in the editor
Freeing Parser Resources
xml_parser_free($parser) releases the parser instance's resources once parsing is complete -- important to call explicitly in scripts that create many parsers (like processing many files in a loop), though PHP also cleans it up automatically when the script ends.
Example: Freeing Parser Resources
<?php
// Declare `$parser`, set to `xml_parser_create()`
$parser = xml_parser_create();
// Call `xml_parse($parser, "<book></book>", true)`
xml_parse($parser, "<book></book>", true);
// Call `xml_parser_free($parser)`
xml_parser_free($parser);
// Print "Parser resources released" to the output
echo "Parser resources released";
?>
Login to try C/C++/Java/PHP code in the editor
- Choosing Expat for small, everyday XML parsing tasks where SimpleXML would be far simpler and perfectly adequate -- Expat's complexity is only worth it for very large files.
- Forgetting that Expat callbacks fire in document order as parsing proceeds -- you cannot "look ahead" to data that has not been reached yet, unlike with a fully-loaded SimpleXML tree.
- Not tracking parsing state (like which element is currently open) across callback calls, since each callback only knows about the single tag or text chunk it was just given.
- xml_parser_create() creates a new Expat parser instance, and xml_set_element_handler() registers callback functions for opening and closing tags.
- xml_parse($parser, $data) feeds XML data to the parser, which processes it and triggers the registered callbacks along the way.
- Expat is a streaming, event-based parser that never holds the entire document in memory at once, making it well-suited to very large XML files.
The Expat XML parser extension has been bundled with PHP since PHP 4 and is enabled by default in most standard installations.
Chapter Quiz — Complete all 24 topics to unlock
0/24 topics done
Complete these topics first:
- PHP Date & Time
- PHP Math Functions
- PHP JSON Handling
- PHP XML Handling
- PHP cURL Introduction
- PHP REST API Basics
- PHP Composer & Packages
- PHP Autoloading
- PHP Design Patterns
- PHP MVC Architecture
- PHP Security Best Practices
- PHP Performance Optimization
- PHP 8 New Features
- PHP Type Declarations
- PHP Match Expression Advanced
- PHP Fibers
- PHP Attributes
- PHP Magic Constants
- PHP Include & Require
- PHP Iterables
- PHP SimpleXML Parser
- PHP SimpleXML Get
- PHP XML Expat Parser
- PHP DOM Parser