When working with XML-based applications you'll often find the need to append elements to your document or even build new XML documents on the fly. PHP's DOM API can be used to dynamically generate well-formed XML documents as well as editing existing files. In this tutorial we will construct a basic XML document used to store information on pending repairs at an auto repair shop, using the DOM API.

Creating a New Document
Let's start by creating a new file. We will pass the value "1.0" to the DOMDocument function which will create a new XML file using XML version 1.0.
$xdoc = new DOMDocument("1.0");
XML requires that a single root element exists and that all other elements exist within the root element. All of our root and child elements will be created using the createElement() function, the data is then created with createTextNode() and then the text is appended to the element and the element appended to the node or document with appendChild. Let's go ahead and create our root and a child element; then append them to the document.
// Create root element and append to $xdoc
$root = $xdoc->createElement('pendingRepairs');
$xdoc->appendChild($root);

// Create a new child and text node for child
$repair1 = $xdoc->createElement('repair');
$root->appendChild($repair1);
Our current XML document looks like this:
<?xml version="1.0"?>
<pendingRepairs>
  <repair>
  </repair>
</pendingRepairs>
OK, so now we have an XML document with a single repair, but no information on that repair. Now we need to create child elements of $repair1 to store some data.
// Create child elements and text nodes, append text to elements
$customer = $xdoc->createElement('customer');
$customerData = $xdoc->createTextNode('Bob Smith');
$customer->appendChild($customerData);
$car = $xdoc->createElement('car');
$carData = $xdoc->createTextNode('Ford Pinto');
$car->appendChild($carData);
$repairtype = $xdoc->createElement('repairtype');
$repairtypeData = $xdoc->createTextNode('rebuild transmission');
$repairtype->appendChild($repairtypeData);

// Append child elements to repair element
$repair1->appendChild($customer);
$repair1->appendChild($car);
$repair1->appendChild($repairtype);

// Save the updated file
$xdoc->save("pendingRepairs.xml");
And our current XML document now looks like this:
<?xml version="1.0"?>
<pendingRepairs>
  <repair>
    <customer>Bob Smith</customer>
    <car>Ford Pinto</car>
    <repairtype>rebuild transmission</repairtype>
  </repair>
</pendingRepairs>
Adding Elements to an Existing Document
This functionality wouldn't do much good if all you could do was create new documents. Next, let's reopen pendingRepairs.xml and enter a new repair. First we'll create a new DOM document and load our existing xml into that document. Then we'll create a new child, append it and resave the file.
// Load the file
$xdoc = new DomDocument;
$xdoc->Load('pendingRepairs.xml');
$root = $xdoc->getElementsByTagName('pendingRepairs')->item(0);

// Create and append a new repair
$repair2 = $xdoc->createElement("repair");
$root->appendChild($repair2);

// Create child elements and text nodes, append text to elements
$customer = $xdoc->createElement('customer');
$customerData = $xdoc->createTextNode('Joe Schmo');
$customer->appendChild($customerData);
$car = $xdoc->createElement('car');
$carData = $xdoc->createTextNode('Chevy Chevelle');
$car->appendChild($carData);
$repairtype = $xdoc->createElement('repairtype');
$repairtypeData = $xdoc->createTextNode('oil change');
$repairtype->appendChild($repairtypeData);

// Append child elements to repair element
$repair2->appendChild($customer);
$repair2->appendChild($car);
$repair2->appendChild($repairtype);

// Save the updated file
$xdoc->save("pendingRepairs.xml");
The updated XML document now looks like this:
<?xml version="1.0"?>
<pendingRepairs>
  <repair>
    <customer>Bob Smith</customer>
    <car>Ford Pinto</car>
    <repairtype>rebuild transmission</repairtype>
  </repair>
  <repair>
    <customer>Joe Schmo</customer>
    <car>Chevy Chevelle</car>
    <repairtype>oil change</repairtype>
  </repair>
</pendingRepairs>
Deleting Elements From an Existing Document
Finally, we'll delete an item from this list by searching the file for a node with a matching customer name and repair type. First, we'll load the XML file using the DOM API, then we'll load the file again, this time using simplexml_load_file (covered in my Jan 1st post). By doing this, we can easily traverse the data loaded using simplexml to find the position of the node we're looking for, then use that position to delete the node using the DOM API. In this case we'll be searching for and removing Bob Smith's transmission rebuild.
// Load DOM file
$xdoc = new DomDocument;
$xdoc->Load('pendingRepairs.xml');
// Load simplexml file
$sdoc = simplexml_load_file('pendingRepairs.xml');
$pos = 0;
foreach($sdoc->repair as $repair) {
  if( ($repair->customer == 'Bob Smith') && ($repair->repairtype == 'rebuild transmission') ) {
	$node = $xdoc->getElementsByTagName('repair')->item($pos);
	$node->parentNode->removeChild($node);
  }
  $pos++;
}

// Save the updated file
$xdoc->save("pendingRepairs.xml");
And there you have a simple introduction to the PHP DOM API. As always, if you have a technique that you think is better or a tweak that improves on this code, please share it in the comments. If you have a tip, trick or an idea for my next post, please don't hesitate to contact me.