Advance PHP 8 programs with output 15 Q/A 5 MCQs

Learning Objectives – after this chapter you will be able to:

  • Explain what XML is, why it is used to exchange data and where it is applied.
  • Write well-formed XML: prolog, elements, tag pairs, empty tags, nesting rules and attributes.
  • Describe an XML document as a tree of ancestors, descendants, parents and children.
  • Read XML with SimpleXML and with the DOM, loop through elements and read attributes.
  • Create XML from PHP data and from a MySQLi query, and query it with XPath.
What is XML?

XML (eXtensible Markup Language) is a markup language – the creators "cheated" a little with the acronym, since the X comes from eXtensible. XML was released by the W3C in 1998 to provide an easy-to-use, standardised way to store self-describing data – data that describes both its content and its structure.

Unlike HTML, XML has no predefined tags. You invent the tags that describe your data – <student>, <price>, <book> – which is what makes it extensible.

Communication between applications

XML by itself does nothing. It is a common ground standard. Its main benefit is that you can take data from one program – for example Microsoft SQL Server or MySQL – convert it into XML, and share that XML with many other programs and platforms. Each receiving platform converts the XML into the structure it normally uses. In this way two very different platforms can communicate.

What makes XML truly powerful is its international acceptance. Many individuals and companies have built XML interfaces for databases, programming languages, office applications, mobile phones and more. Earlier attempts at a standard data format that many different platforms could interpret failed; XML has largely succeeded.

Applications of XML
  • Web services and data feeds – SOAP web services, RSS and Atom news feeds and site maps (sitemap.xml) are XML.
  • Office documents – Microsoft Office (.docx, .xlsx) and LibreOffice files are zipped XML.
  • Configuration files – many applications (Android, Java, .NET) keep settings in XML.
  • Graphics and documents – SVG images, XHTML and e-book formats are XML.
  • Mobile and voice applications – data sent to phones, and VoiceXML, which presents XML documents as audio.
  • File converters – programs that convert existing documents (for example PDF) into XML.

Today JSON (Chapter 39) has replaced XML in many web APIs because it is shorter and maps directly to JavaScript objects. XML remains important for documents, feeds, configuration and enterprise systems, so every PHP developer should know both.

XML Syntax

If you know HTML, XML syntax is easy: it is still a markup language that relies on tags. The following XML document keeps track of the students of a Computer Applications course:

class_list.xml
<?xml version="1.0" encoding="UTF-8"?>
<class_list>
  <student>
    <name>Danish</name>
    <grade>A+</grade>
  </student>
  <student>
    <name>Vikas</name>
    <grade>A-</grade>
  </student>
</class_list>

Reading it, you can see that it has two students, Danish and Vikas. The data almost describes itself – one of the main reasons XML was created.

The XML prolog (optional)

The first line, with its special symbols and attributes, is the XML prolog or XML declaration:

<?xml version="1.0" encoding="UTF-8"?>

It states the version of XML and the character encoding used. It is optional, but if present it must be the very first thing in the document. Always include it; use UTF-8 (older documents use ISO-8859-1).

XML tags

XML tags are very similar to HTML tags. Each element is marked with an opening tag <element> and a closing tag </element>. The opening and closing tags together are a tag pair; all data that belongs to the element appears between them:

<name>Danish</name>
<grade>A+</grade>
The empty (solo) tag

Elements that contain no text can replace the tag pair with one modified opening tag – a slash before the closing bracket: <element />. This tells the XML processor that the element is complete. Example: <photo src="danish.jpg" />.

Rules for well-formed XML

A document that follows the XML syntax rules is well-formed. If a rule is broken, the XML processor stops with an error.

  • Every element must have a closing tag (or be an empty tag <x/>).
  • Tags are case-sensitive: <Student> must be closed with </Student>, not </student>.
  • Elements must be properly nested – the tag ordering rule: a tag opened inside another element must be closed before the outer element closes. <b><i>text</i></b> is correct, <b><i>text</b></i> is not.
  • A document must have exactly one root element that contains all others.
  • Attribute values must be quoted.
  • Special characters must be written as entities: &lt; for <, &amp; for &.
File: htdocs/phpbook/ch38/wellformed.php
<?php
$docs = [
    "good"        => "<student><name>Danish</name></student>",
    "case"        => "<Student><name>Danish</name></student>",
    "nesting"     => "<student><name>Danish</student></name>",
    "two roots"   => "<a>1</a><b>2</b>",
    "unquoted"    => "<friend age=23>Samantha</friend>",
];
libxml_use_internal_errors(true);              // collect errors instead of warnings
foreach ($docs as $label => $xml) {
    $ok = simplexml_load_string($xml);
    if ($ok !== false) {
        echo "$label: well-formed<br>";
    } else {
        $err = libxml_get_errors()[0];
        echo "$label: NOT well-formed – " . trim($err->message) . "<br>";
        libxml_clear_errors();
    }
}
?>
OUTPUT browser · http://localhost/phpbook/ch38/wellformed.php
good: well-formed
case: NOT well-formed – Opening and ending tag mismatch: Student line 1 and student
nesting: NOT well-formed – Opening and ending tag mismatch: name line 1 and student
two roots: NOT well-formed – Extra content at the end of the document
unquoted: NOT well-formed – AttValue: " or ' expected

(The original notes showed the student list with <Student> closed by </student> – the "case" test above shows why that document would be rejected.)

XML Elements

Elements are the meat and potatoes of XML. An element contains the opening and closing tags, child elements and data. In our document the student element contains two child elements:

<student>
  <name>Danish</name>
  <grade>A+</grade>
</student>

XML stores data in a self-explanatory way by putting information into elements: if a piece of text is a title, it goes into a title element.

XML Attributes

Attributes specify additional information about an element – a way of specialising generic elements. An attribute appears inside the opening tag, and its value must be quoted:

<element attributeName="value">
<friend age="23">Samantha</friend>
Element or attribute?

Data can be stored in child elements or in attributes. A common guideline: use elements for the data itself and attributes for metadata such as ids, units or types: <price currency="INR">499</price>.

The XML Tree

The great benefit of XML is that the document itself describes the structure of the data – it fits naturally into a tree, like a family tree with the earliest ancestor at the top. The following document was created by an enterprising kid to keep the inventory of her lemonade stand:

lemonade.xml
<?xml version="1.0" encoding="UTF-8"?>
<inventory>
  <drink>
    <lemonade>
      <price>2.50</price>
      <amount>20</amount>
    </lemonade>
    <pop>
      <price>1.50</price>
      <amount>10</amount>
    </pop>
  </drink>
  <snack>
    <chips>
      <price>4.50</price>
      <amount>60</amount>
    </chips>
  </snack>
</inventory>
inventory root element – the ancestor of every other element
↓
drink, snack children of inventory (siblings of each other)
↓
lemonade, pop / chips children of drink / of snack; grandchildren of inventory
↓
price, amount children of each item – the leaves that hold the data

Figure 38.1 – lemonade.xml as a tree

XML tree rules
  • Descendants – if element A is contained by element B, then A is a descendant of B. In lemonade.xml every element is a descendant of inventory, because it is the root.
  • Ancestors – if element B contains element A, then B is an ancestor of A. drink is an ancestor of lemonade and pop.
  • Parent / child – the direct container is the parent; directly contained elements are its children.
  • Siblings – children of the same parent (lemonade and pop).
Reading XML with SimpleXML

SimpleXML (PHP 5 and later) is an easy way of getting an element's text and attributes if you know the layout of the XML document. Compared with the DOM or the event-based Expat parser, SimpleXML needs just a few lines of code. It converts the XML document into an object:

  • Elements become properties of the SimpleXMLElement object; when there is more than one element with the same name on a level, they can be used like an array.
  • Attributes are accessed like associative-array elements: $element['age'].
  • Element data (text) is converted to a string with (string) or by echoing it.
note.xml
<?xml version="1.0" encoding="UTF-8"?>
<note>
  <to>Rakesh</to>
  <from>Nitin</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>

We want to output the element names and data from the XML file above:

File: htdocs/phpbook/ch38/simplexml.php
<?php
$xml = simplexml_load_file("note.xml");
echo $xml->getName() . "<br>";
foreach ($xml->children() as $child) {
    echo $child->getName() . ": " . $child . "<br>";
}
?>
OUTPUT browser · http://localhost/phpbook/ch38/simplexml.php
note
to: Rakesh
from: Nitin
heading: Reminder
body: Don't forget me this weekend!
Navigating, attributes and XPath
books.xml
<?xml version="1.0" encoding="UTF-8"?>
<library>
  <book id="b1" category="programming">
    <title>PHP: Basics to Advance</title>
    <price currency="INR">499</price>
  </book>
  <book id="b2" category="database">
    <title>MySQL in Practice</title>
    <price currency="INR">399</price>
  </book>
  <book id="b3" category="programming">
    <title>JavaScript Essentials</title>
    <price currency="INR">349</price>
  </book>
</library>
File: htdocs/phpbook/ch38/books.php
<?php
$lib = simplexml_load_file("books.xml");
echo "Number of books: " . count($lib->book) . "<br>";
echo "Second title: " . $lib->book[1]->title . "<br>";
foreach ($lib->book as $b) {
    echo "[{$b['id']}] {$b->title} – {$b->price['currency']} {$b->price} ({$b['category']})<br>";
}
$total = 0;
foreach ($lib->book as $b) $total += (float) $b->price;
echo "Total price: $total<br>";
// XPath: titles of programming books costing more than 300
foreach ($lib->xpath("//book[@category='programming' and price > 300]/title") as $t) {
    echo "XPath result: $t<br>";
}
?>
OUTPUT browser · http://localhost/phpbook/ch38/books.php
Number of books: 3
Second title: MySQL in Practice
[b1] PHP: Basics to Advance – INR 499 (programming)
[b2] MySQL in Practice – INR 399 (database)
[b3] JavaScript Essentials – INR 349 (programming)
Total price: 1247
XPath result: PHP: Basics to Advance
XPath result: JavaScript Essentials
The DOM (Document Object Model)

The W3C DOM provides a standard set of objects for HTML and XML documents and a standard interface for accessing and manipulating them. It is divided into parts (Core, XML and HTML) and levels (DOM Level 1/2/3):

  • Core DOM – a standard set of objects for any structured document.
  • XML DOM – a standard set of objects for XML documents.
  • HTML DOM – a standard set of objects for HTML documents.
XML parsing

To read and update – create and manipulate – an XML document you need an XML parser. There are two basic types:

  • Tree-based parser – transforms the whole document into a tree structure in memory and gives access to the tree elements. The DOM parser (and SimpleXML) are tree-based.
  • Event-based parser – views the document as a series of events (start tag, text, end tag); when an event occurs it calls a function to handle it. PHP's XML Parser (Expat) and XMLReader are event/stream-based and use little memory for very large files.

The DOM sees <from>Nitin</from> as a tree: Level 1 – the XML document; Level 2 – the root element <from>; Level 3 – the text node "Nitin".

Load and output XML

We initialise the XML parser, load the XML and output it:

File: htdocs/phpbook/ch38/domload.php
<?php
$xmlDoc = new DOMDocument();
$xmlDoc->load("note.xml");
print $xmlDoc->saveXML();
?>
OUTPUT browser · http://localhost/phpbook/ch38/domload.php
Rakesh Nitin Reminder Don't forget me this weekend!

The browser shows only the text, because it treats the unknown tags as HTML. If you select View Source you see the complete XML. saveXML() puts the internal XML document into a string so that it can be output.

Looping through XML

We initialise the parser, load the XML and loop through all child nodes of the <note> element:

File: htdocs/phpbook/ch38/domloop.php
<?php
$xmlDoc = new DOMDocument();
$xmlDoc->load("note.xml");
$x = $xmlDoc->documentElement;
foreach ($x->childNodes as $item) {
    print $item->nodeName . " = " . $item->nodeValue . "<br>";
}
?>
OUTPUT browser · http://localhost/phpbook/ch38/domloop.php
#text =
to = Rakesh
#text =
from = Nitin
#text =
heading = Reminder
#text =
body = Don't forget me this weekend!
#text =

You see empty text nodes (#text) between the elements. When XML is generated it often contains white space between the nodes; the DOM parser treats it as ordinary text nodes, which can cause problems if you are not aware of them. Load the document with $xmlDoc->preserveWhiteSpace = false; or skip nodes whose nodeType is not XML_ELEMENT_NODE:

File: htdocs/phpbook/ch38/domloop2.php
<?php
$xmlDoc = new DOMDocument();
$xmlDoc->preserveWhiteSpace = false;
$xmlDoc->load("note.xml");
foreach ($xmlDoc->documentElement->childNodes as $item) {
    if ($item->nodeType == XML_ELEMENT_NODE) {
        print $item->nodeName . " = " . $item->nodeValue . "<br>";
    }
}
echo "Number of 'body' elements: " . $xmlDoc->getElementsByTagName("body")->length;
?>
OUTPUT browser · http://localhost/phpbook/ch38/domloop2.php
to = Rakesh
from = Nitin
heading = Reminder
body = Don't forget me this weekend!
Number of 'body' elements: 1
Creating XML with PHP
With the DOM
File: htdocs/phpbook/ch38/domcreate.php
<?php
$doc = new DOMDocument("1.0", "UTF-8");
$doc->formatOutput = true;
$root = $doc->createElement("class_list");
$doc->appendChild($root);
foreach (["Danish" => "A+", "Vikas" => "A-"] as $name => $grade) {
    $s = $doc->createElement("student");
    $s->setAttribute("batch", "2026");
    $s->appendChild($doc->createElement("name", $name));
    $s->appendChild($doc->createElement("grade", $grade));
    $root->appendChild($s);
}
$doc->save("new_class_list.xml");
echo "<pre>" . htmlspecialchars($doc->saveXML()) . "</pre>";
?>
OUTPUT browser · http://localhost/phpbook/ch38/domcreate.php
<?xml version="1.0" encoding="UTF-8"?>
<class_list>
  <student batch="2026">
    <name>Danish</name>
    <grade>A+</grade>
  </student>
  <student batch="2026">
    <name>Vikas</name>
    <grade>A-</grade>
  </student>
</class_list>
From a MySQLi query with SimpleXML

A typical job is exporting database data as XML for another system:

File: htdocs/phpbook/ch38/export.php
<?php
$conn = new mysqli("localhost", "root", "", "phpbook");
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><courses/>');
foreach ($conn->query("SELECT course_id, course_name, duration, fee FROM courses") as $row) {
    $c = $xml->addChild("course");
    $c->addAttribute("id", $row["course_id"]);
    $c->addChild("name", htmlspecialchars($row["course_name"]));
    $c->addChild("duration", $row["duration"]);
    $c->addChild("fee", $row["fee"]);
}
$dom = dom_import_simplexml($xml)->ownerDocument;
$dom->formatOutput = true;
echo "<pre>" . htmlspecialchars($dom->saveXML()) . "</pre>";
?>
OUTPUT browser · http://localhost/phpbook/ch38/export.php
<?xml version="1.0" encoding="UTF-8"?>
<courses>
  <course id="1">
    <name>Core PHP</name>
    <duration>3 months</duration>
    <fee>4500.00</fee>
  </course>
  <course id="2">
    <name>Advance PHP</name>
    <duration>2 months</duration>
    <fee>6000.00</fee>
  </course>
  <course id="3">
    <name>MySQL</name>
    <duration>1 month</duration>
    <fee>2500.00</fee>
  </course>
  <course id="4">
    <name>Laravel</name>
    <duration>2 months</duration>
    <fee>8000.00</fee>
  </course>
</courses>

To send XML to a client program instead of displaying it, output header("Content-Type: application/xml"); followed by echo $xml->asXML();.

Key Takeaways
  • XML stores self-describing data with tags you define; it is a W3C standard for exchanging data between platforms.
  • Well-formed XML: optional prolog first, one root, every tag closed, case-sensitive tags, correct nesting, quoted attributes.
  • An XML document is a tree of parents, children, siblings, ancestors and descendants.
  • SimpleXML (simplexml_load_file, ->children(), ['attr'], xpath()) is the quickest way to read XML.
  • The DOM (DOMDocument, load, childNodes, createElement, saveXML) reads and builds XML; beware of white-space text nodes.
  • Tree-based parsers load the whole document; event-based parsers (Expat, XMLReader) stream large files.
Program File

Extract the ZIP into C:\xampp\htdocs. It creates the folder phpbook/ch38 used in the file labels above; open the programs at http://localhost/phpbook/… with Apache (and MySQL, where needed) started in the XAMPP Control Panel.

Question / Answer (15 questions)

Answer : eXtensible Markup Language – a W3C markup language for storing and exchanging self-describing data using tags defined by the author.

Answer : Because it has no fixed set of tags; authors define their own tags to describe their data.

Answer : One application converts its data to XML, which any other platform can read and convert into its own structures, so very different systems can exchange data through a common, standard format.

Answer : RSS/Atom feeds and sitemaps, web services (SOAP), office document formats (.docx, .xlsx), configuration files, SVG graphics and VoiceXML (any four).

Answer : The optional declaration <?xml version="1.0" encoding="UTF-8"?> on the first line that states the XML version and character encoding.

Answer : A single tag for an element without content, written with a slash before the closing bracket, e.g. <photo src="a.jpg" />.

Answer : Tags must be closed in the reverse order in which they were opened – an element opened inside another must be closed before the outer element is closed.

Answer : One root element; every element closed; correct nesting; case-sensitive matching tags; quoted attribute values; special characters escaped as entities; the prolog, if present, comes first.

Answer : An element is a tag pair with its content and children, e.g. <name>Danish</name>; an attribute is a name="value" pair inside an opening tag that gives extra information, e.g. <friend age="23">.

Answer : If element A is contained (directly or indirectly) by B, A is a descendant of B and B is an ancestor of A; the root element is the ancestor of all other elements.

Answer : A PHP extension that converts an XML document into an object, so that elements are reached as properties ($xml->book[0]->title) and attributes like array keys ($book['id']).

Answer : $xml = simplexml_load_file("note.xml"); foreach ($xml->children() as $child) { echo $child->getName() . ": " . $child; }

Answer : The W3C Document Object Model – a standard, language-independent set of objects and methods for accessing and changing HTML and XML documents as a tree of nodes.

Answer : A tree-based parser (DOM, SimpleXML) loads the whole document into memory as a tree; an event-based parser (Expat, XMLReader) reads the document sequentially and calls handlers for each start tag, text and end tag, using little memory.

Answer : The white space (new lines and indentation) between elements is stored as text nodes. Set preserveWhiteSpace = false before loading or skip nodes that are not XML_ELEMENT_NODE.
MCQ Test : Check Your Understanding (5 questions)

Select an option and press Check Answer, or answer all questions and press Submit Test to see your score. Each answer comes with an explanation.

Q1. XML tags are:

Show Answer

Correct Answer : B. Defined by the author
XML has no predefined tags.

Q2. Which document is NOT well-formed?

Show Answer

Correct Answer : B. <a><b>x</a></b>
The tags are not properly nested.

Q3. Which PHP function loads an XML file into a SimpleXMLElement?

Show Answer

Correct Answer : B. simplexml_load_file()
simplexml_load_file() returns the object.

Q4. In SimpleXML, the attribute id of $book is read as:

Show Answer

Correct Answer : B. $book['id']
Attributes are accessed like array elements.

Q5. The DOM parser is a:

Show Answer

Correct Answer : B. Tree-based parser
It builds the whole document as a tree.

Bibliography/References

The notes on this page are the author’s own compilation from the e-book PHP: Basics to Advance. Every program was run on Apache with PHP 8 and MariaDB, and the output shown is the real result of that run. The works listed below were consulted and are cited for attribution and further reading. Product names and trademarks belong to their respective owners.

  1. W3C. (2008). Extensible Markup Language (XML) 1.0 (Fifth Edition). https://www.w3.org/TR/xml/
  2. The PHP Group. (n.d.). PHP Manual – SimpleXML. https://www.php.net/manual/en/book.simplexml.php
  3. The PHP Group. (n.d.). PHP Manual – Document Object Model (DOM). https://www.php.net/manual/en/book.dom.php
  4. The PHP Group. (n.d.). PHP Manual – XML Parser (Expat). https://www.php.net/manual/en/book.xml.php
  5. MDN contributors. (n.d.). XML introduction. MDN Web Docs. https://developer.mozilla.org/en-US/docs/Web/XML/XML_introduction