start page | rating of books | rating of authors | reviews | copyrights

Book HomePHP CookbookSearch this book

12.3. Generating XML with the DOM

12.3.1. Problem

You want to generate XML but want to do it in an organized way instead of using print and loops.

12.3.2. Solution

Use PHP's DOM XML extension to create a DOM object; then, call dump_mem( ) or dump_file( ) to generate a well-formed XML document:

// create a new document
$dom = domxml_new_doc('1.0');

// create the root element, <book>, and append it to the document
$book = $dom->append_child($dom->create_element('book'));

// create the title element and append it to $book
$title = $book->append_child($dom->create_element('title'));

// set the text and the cover attribute for $title
$title->append_child($dom->create_text_node('PHP Cookbook'));
$title->set_attribute('cover', 'soft');

// create and append author elements to $book
$sklar = $book->append_child($dom->create_element('author'));
// create and append the text for each element
$sklar->append_child($dom->create_text_node('Sklar'));

$trachtenberg = $book->append_child($dom->create_element('author'));
$trachtenberg->append_child($dom->create_text_node('Trachtenberg'));

// print a nicely formatted version of the DOM document as XML
echo $dom->dump_mem(true);
<?xml version="1.0"?>
<book>
  <title cover="soft">PHP Cookbook</title>
  <author>Sklar</author>
  <author>Trachtenberg</author>
</book>

12.3.3. Discussion

A single element is known as a node . Nodes can be of a dozen different types, but the three most popular are elements, attributes, and text. Given this:

<book cover="soft">PHP Cookbook</book>

PHP's DOM XML functions refer to book as type XML_ELEMENT_NODE, cover="soft" maps to an XML_ATTRIBUTE_NODE , and PHP Cookbook is a XML_TEXT_NODE.

For DOM parsing, PHP uses libxml, developed for the Gnome project. You can download it from http://www.xmlsoft.org. To activate it, configure PHP with --with-dom.

The revamped PHP 4.3 DOM XML functions follow a pattern. You create an object as either an element or a text node, add and set any attributes you want, and then append it to the tree in the spot it belongs.

Before creating elements, create a new document, passing the XML version as the sole argument:

$dom = domxml_new_doc('1.0');

Now create new elements belonging to the document. Despite being associated with a specific document, nodes don't join the document tree until appended:

$book_element = $dom->create_element('book');
$book = $dom->append_child($book_element);

Here a new book element is created and assigned to the object $book_element. To create the document root, append $book_element as a child of the $dom document. The result, $book, refers to the specific element and its location within the DOM object.

All nodes are created by calling a method on $dom. Once a node is created, it can be appended to any element in the tree. The element from which we call the append_child( ) method determines the location in the tree where the node is placed. In the previous case, $book_element is appended to $dom. The element appended to $dom is the top-level node, or the root node.

You can also append a new child element to $book. Since $book is a child of $dom, the new element is, by extension, a grandchild of $dom:

$title_element = $dom->create_element('title');
$title = $book->append_child($title_element);

By calling $book->append_child( ), this code places the $title_element element under the $book element.

To add the text inside the <title></title> tags, create a text node using create_text_node( ) and append it to $title:

$text_node = $dom->create_text_node('PHP Cookbook');
$title->append_child($text_node);

Since $title is already added to the document, there's no need to reappend it to $book.

The order in which you append children to nodes isn't important. The following four lines, which first append the text node to $title_element and then to $book, are equivalent to the previous code:

$title_element = $dom->create_element('title');
$text_node = $dom->create_text_node('PHP Cookbook');

$title_element->append_child($text_node);
$book->append_child($title_element);

To add an attribute, call set_attribute( ) upon a node, passing the attribute name and value as arguments:

$title->set_attribute('cover', 'soft');

If you print the title element now, it looks like this:

<title cover="soft">PHP Cookbook</title>

Once you're finished, you can output the document as a string or to a file:

// put the string representation of the XML document in $books
$books = $dom->dump_mem( );

// write the XML document to books.xml
$dom->dump_file('books.xml', false, true);

The only parameter dump_mem( ) takes is an optional boolean value. An empty value or false means "return the string as one long line." A true value causes the XML to be nicely formatted with child nodes indented, like this:

<?xml version="1.0"?>
<book>
  <title cover="soft">PHP Cookbook</title>
</book>

You can pass up to three values to dump_file( ). The first one, which is mandatory, is the filename. The second is whether the file should be compressed with gzip. The final value is the same pretty formatting option as dump_mem( ).

12.3.4. See Also

Recipe 12.2 for writing XML without DOM; Recipe 12.4 for parsing XML with DOM; documentation on domxml_new_dom( ) at http://www.php.net/domxml-new-dom and the DOM functions in general at http://www.php.net/domxml; more information about the underlying DOM C library at http://xmlsoft.org/.



Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.