21. Processing XML Documents
The web services we have written so far exchange JSON data. The XML (eXtensible Markup Language) has long been the most widely used exchange format, and it is still commonly encountered: SOAP web services, RSS feeds, configuration files, office documents (a [.odt] or [.docx] file is an archive of XML files). PHP provides two APIs for working with it:
- [SimpleXML]: a very simple API, where the document elements become object properties;
- [DOM] (Document Object Model): the standard API of W3C, which is more comprehensive and also allows you to modify a document. PHP 8.4 introduced a new version, in the [Dom] namespace, compliant with the current web standard.
The scripts in this chapter are located in the [scripts-console/xml] folder:
21.1. The document under consideration
We are considering the following file: XML [data.xml]:
A XML document is a tree of elements:
- line 1: the prolog, which specifies the version of XML and the document’s character encoding;
- lines 3–21: the root element [tribe]. A XML document has exactly one root;
- lines 4–12: the [teacher] element, a child of [tribe]. It has two children, [person] and [section];
- line 5: the element [person] has an attribute [gender] with a value of [M];
- line 9: an element can contain both other elements and text;
- lines 13–20: the element [student], which has the same structure as [teacher].
21.2. Processing with SimpleXML
We analyze this document using the following [simplexml-01.php] script:
Comments
- line 6: The filename XML is a constant. The script is executed in its own folder, that of [data.xml];
- Line 9: The [simplexml_load_file] function loads the document and returns an object of type [SimpleXMLElement], which represents the root element [tribe]. In the event of an error (missing file, malformed XML), it returns [false], which we test on line 10;
- line 15: display of the document. [print_r] shows how [SimpleXML] views the tree XML;
- line 17: child elements are accessed as properties ([$xml->teacher->person]), and attributes as array keys ([['gender']]). Note that the root [tribe] does not appear in the code: [$xml] is already that element;
- line 19: [$xml->teacher->person->lastName] is not a string but an object [SimpleXMLElement]. Converting [(string)] yields its text. With [declare(strict_types=1)], it is best to perform this conversion explicitly before passing the value to a function that expects a string;
- Line 21: the value of the [gender] attribute;
- Lines 26–27: [isset] determines whether an element exists. The script PHP 7 displayed the Boolean result using [print], which returns [1] for [true] and an empty string for [false]. We use [var_export], which displays [true] or [false];
- line 29: the conversion [(int)] returns the integer value of the element’s text;
- line 32: the method [xpath] evaluates an expression XPath. The expression [//person] refers to all [person] elements in the document, regardless of their level. This returns an array of [SimpleXMLElement].
Console output
- Lines 2–38: the document XML in the form of a [SimpleXMLElement] object. Note that the text [this is a comment] does not appear: [print_r] shows only the elements and attributes;
- lines 39–42: an attribute is also a [SimpleXMLElement] object;
- lines 43–48: the values read from the document;
- lines 49–50: the XPath traversal of the two people.
21.3. Processing with the new DOM API from PHP 8.4
Starting with PHP 8.4, the [Dom] namespace offers a new DOM API: the [Dom\XMLDocument] class for XML documents and the [Dom\HTMLDocument] class for HTML5 documents. It is a better replacement for the old [DOMDocument] class (which is still available): it complies with the current DOM standard and provides the [querySelector] and [querySelectorAll] methods familiar to JavaScript developers. These methods allow you to search for elements using CSS selectors.
The [dom-01.php] script uses the same document:
Comments
- line 7: the [XMLDocument] class in the [Dom] namespace;
- Line 14: The static method [createFromFile] loads the document. Unlike [simplexml_load_file], it throws an exception if an error occurs;
- line 20: the property [documentElement] is the root element; [tagName] is its name;
- line 22: the selector CSS [teacher > person] refers to an element [person] that is a direct child of an element [teacher]. [querySelector] returns the first matching element, or [null] if there are none;
- line 23: the [textContent] property is the text contained in the element;
- line 24: the value of an attribute;
- line 27: a missing element returns [null];
- line 29: all [person] elements in the document;
- Line 31: If the element [firstName] were missing, [querySelector('firstName')] would result in [null]. The null-safe operator [?->] (PHP 8.0) then returns [null] instead of causing an error, and the operator [??] replaces this [null] with ['?'];
- line 37: the API DOM also allows the document to be modified: here, the text of the [section] element is changed;
- line 39: [saveXml] returns the text XML from the document, or from one of its elements if it is passed as a parameter.
Console output
- line 16: the modification made by the script.
These two examples do not show all the capabilities of [SimpleXML] and [DOM], but they are sufficient for us to write a new version of the application exercise. The documentation for PHP describes them in detail: SimpleXML and DOM.