Manually generating markup will in most cases require that the document be generated from the top down. And it is up to the developer to make sure all tags are complete with matching opening and closing tags. You can optimize this with the help of a few PHP functions or classes, but PHP comes with a set of built-in objects and functions. The Document Object Model (DOM) provides a treelike structure that makes it easy to create and handle markup.
PHP has two implementations of DOM: DOM and DOMXML.
The DOMXML extension was moved to the PHP Extension and Application Repository (PECL) repository and will no longer be bundled with PHP as of PHP 5.0.0.
The DOM extension is bundled and enabled by default (no need for recompilations to use it) on both Unix and Windows platforms from PHP 5.0.0. It is a replacement for the DOMXML extension from PHP 4, and it follows the DOM Level 2 standard.
You can handle DOM documents by creating an instance of the DomDocument()class. This class provides methods to create and add elements to the object tree. The DomDocument()con- structor takes two parameters; the first is a string indicating the DOM version to be used, and the second is an optional encoding parameter. These values create the content of the <?xml ?>
tag located as the first tag in an XML document.
The DOM extension makes it possible to create both HTML and XML documents from the same object tree by callingsaveHTML()or saveXML()on the DomDocument()object. The next example shows how to create a simple HTML document with the DOM extension.
The Code
<?php
// Example 14-3-1.php
$root = new DomDocument('1.0', 'iso-8859-1');
$html = $root->createElement("html");
$body = $root->createElement("body");
$table = $root->createElement("table");
$row = $root->createElement("tr");
$cell = $root->createElement("td", "value1");
$row->appendChild($cell);
$cell = $root->createElement("td", "value2");
$row->appendChild($cell);
1 4 - 3 ■ U S I N G D O M TO G E N E R AT E M A R K U P 516
$table->appendChild($row);
$body->appendChild($table);
$html->appendChild($body);
$root->appendChild($html);
echo $root->saveHTML();
?>
How It Works
The first step is to create an instance of DomDocument(). This then creates instances of the DomElement()class for each tag you want in the file.
This example uses two methods to create and add elements to the object tree. The createElement()method can be called with one or two string parameters. The first parameter specifies the node or element name, and the second parameter specifies an optional value. If a value is passed, it will be added between the opening and closing tags for that element. In the previous example, you created the html, body, table, and trelements without any values.
These elements will only contain other elements. The two tdelements were created with a value, and the value will end up as the data in the table cells in the resulting HTML document.
The other method, appendChild(), places the elements in the object tree, and as shown in the example, you can use this method both on the root element and on any of the child elements in the tree.
The output from this code will be sent to the client in the form of a valid HTML document.
The default content type for output generated with PHP is text/html, so you do not have to send an explicit header.
<html><body><table><tr>
<td>value1</td>
<td>value2</td>
</tr></table></body></html>
The object tree is maintained in memory, so it is possible to add elements to a node even after it has been added to the tree. So, if you want to add another row to the table in the previ- ous example, you can do so at any time before the output is generated, as shown next.
The Code
<?php
// Example 14-3-2.php
$root = new DomDocument('1.0', 'iso-8859-1');
$html = $root->createElement("html");
$body = $root->createElement("body");
$table = $root->createElement("table");
$row = $root->createElement("tr");
1 4 - 3 ■ U S I N G D O M TO G E N E R AT E M A R K U P 517
$cell = $root->createElement("td", "value1");
$row->appendChild($cell);
$cell = $root->createElement("td", "value2");
$row->appendChild($cell);
$table->appendChild($row);
$body->appendChild($table);
$html->appendChild($body);
$root->appendChild($html);
$row = $root->createElement("tr");
$cell = $root->createElement("td", "value3");
$row->appendChild($cell);
$cell = $root->createElement("td", "value4");
$row->appendChild($cell);
$table->appendChild($row);
echo $root->saveHTML();
?>
How It Works
This is basically the same code as used in the previous example, but it shows how you can add elements to other elements deep in the tree, even after these have been added to the tree. This will generate the following output:
<html><body><table>
<tr>
<td>value1</td>
<td>value2</td>
</tr>
<tr>
<td>value3</td>
<td>value4</td>
</tr>
</table></body></html>
When an element has been created with or without the optional value, it is possible to add text or character data to the element. You can do this with createTextNode()or createCDATASection(). Both methods are available on the DomDocument()object, and they both return an object that must be appended to the object tree with the appendChild() method. The next example shows how you can use the createTextNode()method to add multiple text strings to a body element in an HTML document.
1 4 - 3 ■ U S I N G D O M TO G E N E R AT E M A R K U P 518
The Code
<?php
// Example 14-3-3.php
$root = new DomDocument('1.0', 'iso-8859-1');
$html = $root->createElement("html");
$body = $root->createElement("body");
$txt = $root->createTextNode(
utf8_encode("This is a text with Danish characters ổứồ\n") );
$body->appendChild($txt);
$txt = $root->createTextNode(
utf8_encode("& we could continue to add text to this document") );
$body->appendChild($txt);
$html->appendChild($body);
$root->appendChild($html);
echo $root->saveHTML();
?>
How It Works
This example will create a document with two elements (htmland body). Inside the inner body tag, you will add two text nodes. Using the utf8_encode()function will ensure that all special characters are converted correctly.
<html><body>This is a text with Danish characters æøå
& we could continue to add text to this document</body></html>
Using CDATAsections, or character data sections, is important when handling XML docu- ments. The CDATAsections allow the document to contain sections with special characters and linefeeds. You can use the CDATAsections to include JavaScript code in an XML document, as shown in the next example.
The Code
<?php
// Example 14-3-4.php
$root = new DomDocument('1.0', 'iso-8859-1');
$html = $root->createElement("html");
$body = $root->createElement("body");
$script = $root->createElement("script");
1 4 - 3 ■ U S I N G D O M TO G E N E R AT E M A R K U P 519
$txt = $root->createCDATASection(
"function SubmitForm() {
if (document.myform.name.value == '') { alert('Name cannot be empty');
document.myform.name.focus();
} }"
);
$script->appendChild($txt);
$body->appendChild($script);
$html->appendChild($body);
$root->appendChild($html);
header("Content-Type: text/xml");
echo $root->saveXML();
?>
How It Works
You can use the createCDATASection()method like the other create methods to create the node that is later appended to the object tree with the appendChild()method. This example also uses the header()function to overwrite the default content type, and it uses the saveXML() method to create an XML document.
<?xml version="1.0" encoding="iso-8859-1"?>
<html><body><script><![CDATA[function SubmitForm() { if (document.myform.name.value == '') {
alert('Name cannot be empty');
document.myform.name.focus();
}
}]]></script></body></html>