DOM and SimpleXML

PHP's DOM and SimpleXML Extensions

SimpleXML maps elements to object properties and attributes to array keys, which suits reading regular feeds. DOM is the full W3C API; PHP 8.4 added Dom\XMLDocument, a standards-compliant DOM with CSS selectors, alongside the classic DOMDocument. XMLReader and XMLWriter stream large files:

read.php: SimpleXML for reading, Dom\XMLDocument for editingPHP
<?php
// SimpleXML: elements as properties, attributes as array keys
$catalog = simplexml_load_file('booknest-catalog.xml');
foreach ($catalog->book as $book) {
    if ((float) $book->supply->price >= 20) {
        printf("%s %-26s %6.2f\n", $book['id'], $book->title, (float) $book->supply->price);
    }
}
// PHP 8.4+ Dom\XMLDocument: standards-based DOM with CSS selectors
$doc = Dom\XMLDocument::createFromFile('booknest-catalog.xml');
$b3 = $doc->querySelector('book[id="b3"]');
$b3->querySelector('availability')->textContent = 'in-stock';
echo $doc->saveXml($b3->querySelector('supply')), PHP_EOL;
echo 'PHP ', PHP_VERSION, ', libxml ', LIBXML_DOTTED_VERSION, PHP_EOL;
Output
b2 Patterns of the Deep Web    39.50
b3 Salt and Saffron            24.00
b6 Gardens in Glass            21.30
<supply>
      <availability>in-stock</availability>
      <price currency="USD">24.00</price>
    </supply>
PHP 8.5.4, libxml 2.15.2

Cast SimpleXML values ((float), (string)) before comparing them.


DOM Reference

Reference for the classes exposed by PHP's DOM extension (php.net/manual/en/book.dom.php 331 ). All node types extend DOMNode.

DOMNode

readonly string $nodeName;
string $nodeValue;
readonly int $nodeType;
readonly DOMNode $parentNode;
readonly DOMNodeList $childNodes;
readonly DOMNode $firstChild;
readonly DOMNode $lastChild;
readonly DOMNode $previousSibling;
readonly DOMNode $nextSibling;
readonly DOMNamedNodeMap $attributes;
readonly DOMDocument $ownerDocument;
readonly string $namespaceURI;
string $prefix;
readonly string $localName;
readonly string $baseURI;
readonly string $textContent;
DOMNode appendChild 331 (DOMNode $newnode)
string C14N 331 ([bool $exclusive [, bool $with_comments [, array $xpath [, array $ns_prefixes]]]])
int C14NFile 331 (string $uri [, bool $exclusive [, bool $with_comments [, array $xpath [, array $ns_prefixes]]]])
DOMNode cloneNode 331 ([bool $deep])
int getLineNo 331 (void)
string getNodePath 331 (void)
bool hasAttributes 331 (void)
bool hasChildNodes 331 (void)
DOMNode insertBefore 331 (DOMNode $newnode [, DOMNode $refnode])
bool isDefaultNamespace 331 (string $namespaceURI)
bool isSameNode 331 (DOMNode $node)
bool isSupported 331 (string $feature, string $version)
string lookupNamespaceURI 331 (string $prefix)
string lookupPrefix 331 (string $namespaceURI)
void normalize 331 (void)
DOMNode removeChild 331 (DOMNode $oldnode)
DOMNode replaceChild 331 (DOMNode $newnode, DOMNode $oldnode)

DOMDocument extends DOMNode

readonly string $actualEncoding;
readonly DOMConfiguration $config;
readonly DOMDocumentType $doctype;
readonly DOMElement $documentElement;
string $documentURI;
string $encoding;
bool $formatOutput;
readonly DOMImplementation $implementation;
bool $preserveWhiteSpace = true;
bool $recover;
bool $resolveExternals;
bool $standalone;
bool $strictErrorChecking = true;
bool $substituteEntities;
bool $validateOnParse = false;
string $version;
readonly string $xmlEncoding;
bool $xmlStandalone;
string $xmlVersion;
__construct 331 ([string $version [, string $encoding]])
DOMAttr createAttribute 331 (string $name)
DOMAttr createAttributeNS 331 (string $namespaceURI, string $qualifiedName)
DOMCDATASection createCDATASection 331 (string $data)
DOMComment createComment 331 (string $data)
DOMDocumentFragment createDocumentFragment 331 (void)
DOMElement createElement 331 (string $name [, string $value])
DOMElement createElementNS 331 (string $namespaceURI, string $qualifiedName [, string $value])
DOMEntityReference createEntityReference 331 (string $name)
DOMProcessingInstruction createProcessingInstruction 331 (string $target [, string $data])
DOMText createTextNode 331 (string $content)
DOMElement getElementById 331 (string $elementId)
DOMNodeList getElementsByTagName 331 (string $name)
DOMNodeList getElementsByTagNameNS 331 (string $namespaceURI, string $localName)
DOMNode importNode 331 (DOMNode $importedNode [, bool $deep])
mixed load 331 (string $filename [, int $options = 0])
bool loadHTML 331 (string $source [, int $options = 0])
bool loadHTMLFile 331 (string $filename [, int $options = 0])
mixed loadXML 331 (string $source [, int $options = 0])
void normalizeDocument 331 (void)
bool registerNodeClass 331 (string $baseclass, string $extendedclass)
bool relaxNGValidate 331 (string $filename)
bool relaxNGValidateSource 331 (string $source)
int save 331 (string $filename [, int $options])
string saveHTML 331 ([DOMNode $node = NULL])
int saveHTMLFile 331 (string $filename)
string saveXML 331 ([DOMNode $node [, int $options]])
bool schemaValidate 331 (string $filename [, int $flags])
bool schemaValidateSource 331 (string $source [, int $flags])
bool validate 331 (void)
int xinclude 331 ([int $options])

For the save*() functions, only LIBXML_NOEMPTYTAG is a supported $options value. For the load*() functions and xinclude(), $options accepts any combination of the libxml constants 331 : LIBXML_COMPACT, LIBXML_DTDATTR, LIBXML_DTDLOAD, LIBXML_DTDVALID, LIBXML_HTML_NOIMPLIED, LIBXML_HTML_NODEFDTD, LIBXML_NOBLANKS, LIBXML_NOCDATA, LIBXML_NOEMPTYTAG, LIBXML_NOENT, LIBXML_NOERROR, LIBXML_NONET, LIBXML_NOWARNING, LIBXML_NOXMLDECL, LIBXML_NSCLEAN, LIBXML_PARSEHUGE, LIBXML_PEDANTIC, LIBXML_XINCLUDE, LIBXML_ERR_ERROR, LIBXML_ERR_FATAL, LIBXML_ERR_NONE, LIBXML_ERR_WARNING, LIBXML_VERSION, LIBXML_DOTTED_VERSION, LIBXML_SCHEMA_CREATE. The methods loadXML(), loadHTML(), saveXML(), saveHTML(), relaxNGValidateSource(), and schemaValidateSource() operate on an in-memory string rather than a file.


DOMElement extends DOMNode

readonly bool $schemaTypeInfo;
readonly string $tagName;
__construct 331 (string $name [, string $value [, string $namespaceURI]])
string getAttribute 331 (string $name)
DOMAttr getAttributeNode 331 (string $name)
DOMAttr getAttributeNodeNS 331 (string $namespaceURI, string $localName)
string getAttributeNS 331 (string $namespaceURI, string $localName)
DOMNodeList getElementsByTagName 331 (string $name)
DOMNodeList getElementsByTagNameNS 331 (string $namespaceURI, string $localName)
bool hasAttribute 331 (string $name)
bool hasAttributeNS 331 (string $namespaceURI, string $localName)
bool removeAttribute 331 (string $name)
bool removeAttributeNode 331 (DOMAttr $oldnode)
bool removeAttributeNS 331 (string $namespaceURI, string $localName)
DOMAttr setAttribute 331 (string $name, string $value)
DOMAttr setAttributeNode 331 (DOMAttr $attr)
DOMAttr setAttributeNodeNS 331 (DOMAttr $attr)
void setAttributeNS 331 (string $namespaceURI, string $qualifiedName, string $value)
void setIdAttribute 331 (string $name, bool $isId)
void setIdAttributeNode 331 (DOMAttr $attr, bool $isId)
void setIdAttributeNS 331 (string $namespaceURI, string $localName, bool $isId)

DOMAttr extends DOMNode

readonly string $name;
readonly DOMElement $ownerElement;
readonly bool $schemaTypeInfo;
readonly bool $specified;
string $value;
__construct 331 (string $name [, string $value])
bool isId 331 (void)

DOMDocumentFragment extends DOMNode

bool appendXML 331 (string $data)

DOMDocumentType extends DOMNode

readonly string $Id; // publicId
readonly string $systemId;
readonly string $name;
readonly DOMNamedNodeMap $entities;
readonly DOMNamedNodeMap $notations;
readonly string $internalSubset;

DOMNotation extends DOMNode

readonly string $Id; // publicId
readonly string $systemId;

DOMEntity extends DOMNode

readonly string $Id; // publicId
readonly string $systemId;
readonly string $notationName;
string $actualEncoding;
readonly string $encoding;
readonly string $version;

DOMEntityReference extends DOMNode

__construct 331 (string $name)

DOMProcessingInstruction extends DOMNode

readonly string $target;
string $data;
__construct 331 (string $name [, string $value])

DOMCharacterData extends DOMNode

string $data;
readonly int $length;
void appendData 331 (string $data)
void deleteData 331 (int $offset, int $count)
void insertData 331 (int $offset, string $data)
void replaceData 331 (int $offset, int $count, string $data)
string substringData 331 (int $offset, int $count)

DOMComment extends DOMCharacterData

__construct 331 ([string $value])

DOMText extends DOMCharacterData

readonly string $wholeText;
__construct 331 ([string $value])
bool isWhitespaceInElementContent 331 (void)
DOMText splitText 331 (int $offset)

DOMCdataSection extends DOMText

__construct 331 (string $value)

DOMNamedNodeMap implements Traversable

readonly int $length;
DOMNode getNamedItem 331 (string $name)
DOMNode getNamedItemNS 331 (string $namespaceURI, string $localName)
DOMNode item 331 (int $index)

DOMNodeList implements Traversable

readonly int $length;
DOMNode item 331 (int $index)

DOMException extends Exception

readonly int $code;

DOMImplementation

__construct 331 (void)
DOMDocument createDocument 331 ([string $namespaceURI = NULL [, string $qualifiedName = NULL [, DOMDocumentType $doctype = NULL]]])
DOMDocumentType createDocumentType 331 ([string $qualifiedName = NULL [, string $Id = NULL [, string $systemId = NULL]]])
bool hasFeature 331 (string $feature, string $version)

Reading

To read an XML document, load it into a DOMDocument with load(), then navigate it with methods such as getElementsByTagName().

If the document contains XInclude directives, call $doc->xinclude() after loading to resolve them and merge in the included content. The example below loads people.xml, which pulls in the two <person> elements of people2.xml via <xi:include>, then iterates over all four <person> elements, printing each child element's text and the id attribute.
ch08-people.xml, ch08-people2.xml, ch08-read-xinclude.phpXML
merged-02-01-ch08-people.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!-- people.xml -->
<people xmlns:xi="http://www.w3.org/2003/XInclude">
   <xi:include href="people2.xml" parse="xml">
      <xi:fallback>
      <error>xinclude: people2.xml not found</error>
      </xi:fallback>
   </xi:include>

   <person id="p3">
      <name>Eric Lee</name>
      <gender>m</gender>
      <age>35</age>
   </person>
   <person id="p4">
      <name>Serena</name>
      <gender>f</gender>
      <age>25</age>
   </person>
</people>
merged-02-02-ch08-people2.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!-- people2.xml -->
<people>
   <person id="p1">
      <name>Alexander Mike</name>
      <gender>m</gender>
      <age>40</age>
   </person>
   <person id="p2">
      <name>Celeste</name>
      <gender>f</gender>
      <age>15</age>
   </person>
</people>
<!DOCTYPE html>
<html><head></head><body><?php

$doc = new DOMDocument();
$doc->load('people.xml');
$doc->xinclude();
$persons = $doc->getElementsByTagName('person');
foreach ($persons as $person){
   $v = $person->getElementsByTagName('*');
   for ($i=0; $i<$v->length; $i++){
      echo $v->item($i)->nodeValue.",";
   }
   echo $person->attributes->getNamedItem('id')->value;
   echo "<br/>";
}

?></body></html>
Output
Alexander Mike,m,40,p1
Celeste,f,15,p2
Eric Lee,m,35,p3
Serena,f,25,p4

Writing

Build a new XML document with DOMDocument, then write it to disk with save(). The example below constructs book.xml: a document with a top-level comment, a root <book> element, and a nested <part> element whose title attribute is registered as an ID attribute via setIdAttribute(). One <chapter> child is appended to <part> for each entry in a PHP array.
ch08-write-book.phpPHP
<!DOCTYPE html>
<html><head></head><body><?php

$doc = new DOMDocument("1.0","UTF-8");
$comment=$doc->createComment("This is 'book.xml'.");
$doc->appendChild($comment);
$book=$doc->createElement("book");
$doc->appendChild($book);
$part1 = new DOMElement("part");
$book->appendChild($part1);
$part1->setAttribute("title","Core");
$part1->setIdAttribute("title",true);
$chapters = ["HTML","CSS","JavaScript","PHP","SQL","XML"];
foreach ($chapters as $chapter){
   $c = new DOMElement("chapter",$chapter);
   $part1->appendChild($c);
}
$doc->save("book.xml");

?></body></html>
Opening the resulting book.xml in an XML-aware viewer shows the tree built above – a book root containing a part element with six chapter children:

Tree view of the generated book.xml document showing a book element containing chapters for HTML, CSS, JavaScript, PHP, SQL, and XML