XML Tutorial · XML in Code · Lesson 18 of 28
XML in PHP
SimpleXML for quick reading, DOMDocument and DOMXPath for full control, and XMLWriter and XMLReader for large documents.
Which API?
| API | Best for |
|---|---|
| SimpleXML | Reading small, simple documents with object syntax ($order->item[0]['sku']) |
| DOMDocument + DOMXPath | Full control: namespaces, editing, XPath, validation |
| XMLWriter | Writing large documents piece by piece |
| XMLReader | Reading large documents as a stream |
All are built on libxml2 and usually enabled by default. PHP 8 and libxml2 2.9+ don't load external entities
unless you pass LIBXML_NOENT, which keeps the defaults safe (see XML security).
SimpleXML
<?php
$shop = simplexml_load_string('<shop>
<product sku="TEA-01" category="drinks"><name>Green tea</name><price>3.50</price><stock>40</stock></product>
<product sku="COF-02" category="drinks"><name>Coffee beans</name><price>9.90</price><stock>0</stock></product>
<product sku="MUG-07" category="kitchen"><name>Camel mug</name><price>12.00</price><stock>15</stock></product>
<product sku="PAN-03" category="kitchen"><name>Frying pan</name><price>29.00</price><stock>4</stock></product>
</shop>');
foreach ($shop->product as $p) {
printf("%-7s %-13s %6.2f\n", $p['sku'], $p->name, (float) $p->price);
}
$kitchen = $shop->xpath("//product[@category='kitchen']/name");
echo "kitchen: ", implode(", ", array_map('strval', $kitchen)), "\n";
echo "first price: ", $shop->product[0]->price, "\n";
Output
TEA-01 Green tea 3.50 COF-02 Coffee beans 9.90 MUG-07 Camel mug 12.00 PAN-03 Frying pan 29.00 kitchen: Camel mug, Frying pan first price: 3.50
DOMDocument
<?php
$doc = new DOMDocument();
$doc->preserveWhiteSpace = false;
$doc->loadXML('<shop>
<product sku="TEA-01" category="drinks"><name>Green tea</name><price>3.50</price><stock>40</stock></product>
<product sku="COF-02" category="drinks"><name>Coffee beans</name><price>9.90</price><stock>0</stock></product>
<product sku="MUG-07" category="kitchen"><name>Camel mug</name><price>12.00</price><stock>15</stock></product>
<product sku="PAN-03" category="kitchen"><name>Frying pan</name><price>29.00</price><stock>4</stock></product>
</shop>');
$xp = new DOMXPath($doc);
foreach ($xp->query("//product[stock = 0]") as $p) {
$p->parentNode->removeChild($p);
}
$new = $doc->createElement("product");
$new->setAttribute("sku", "SPN-11");
$new->appendChild($doc->createElement("name", "Wooden spoon"));
$doc->documentElement->appendChild($new);
echo $xp->evaluate("count(//product)"), " products\n";
$doc->formatOutput = true;
echo $doc->saveXML($new);
Output
4 products <product sku="SPN-11"> <name>Wooden spoon</name> </product>
XMLWriter
<?php
$w = new XMLWriter();
$w->openMemory();
$w->setIndent(true);
$w->startDocument("1.0", "UTF-8");
$w->startElement("feed");
foreach (["Tea & cake", "Coffee <beans>"] as $i => $title) {
$w->startElement("entry");
$w->writeAttribute("id", (string) ($i + 1));
$w->writeElement("title", $title); // escaped automatically
$w->endElement();
}
$w->endElement();
echo $w->outputMemory();
Output
<?xml version="1.0" encoding="UTF-8"?> <feed> <entry id="1"> <title>Tea & cake</title> </entry> <entry id="2"> <title>Coffee <beans></title> </entry> </feed>
Test yourself
Which PHP API reads very large XML files without loading them into memory?
XMLReaderSimpleXMLDOMDocumentjson_decode
Show answer
Answer: XMLReader
XMLReader is a pull parser that moves through the document node by node.