Easily Create XML In PHP Using A Data Array

I’ve been working with the Google Contacts API lately and needed to construct some XML as a part of that. PHP’s DOMDocument works really great for this, but it can get complicated fast as you need to create lots of variables for all of your elements, children, etc. It can make it quite hard to do dynamically.

An easier method would be to just convert an array into XML, the opposite of simplexml_load_string() if you will. So I wrote some code that does exactly that and I thought I’d share it incase anyone else would find it helpful. 🙂

Start by creating your array of data. I used a numeric array instead of an associative array because you can have duplicate elements in XML while you cannot have duplicate array keys.

$data = array(
	'name' => 'toplevelelement', // "name" required, all else optional
	'attributes' => array(
		'foo' => 'bar',
		'fruit' => 'apple',
	),
	'value' => 'Some random value.',
	array(
		'name' => 'achildelement',
		'value'=> 'Value',
	),
	array(
		'name' => 'anotherchildelement',
		'attributes' => array(
			'some' => 'attr',
		),
		array(
			'name' => 'grandchildelement',
		),
	),
);

An array such as that is easy to dynamically create based on your source data, it’s easy to read, and can be fairly easily manipulated.

name is the only required item of each array and it’s the tag name of the element. attributes is an array of attributes for the element and value is the value. Both of these are optional. Any children arrays are children elements and their structures should be the same.

Now here’s the code I wrote that converts the above array into some XML:

function generate_xml_element( $dom, $data ) {
	if ( empty( $data['name'] ) )
		return false;

	// Create the element
	$element_value = ( ! empty( $data['value'] ) ) ? $data['value'] : null;
	$element = $dom->createElement( $data['name'], $element_value );

	// Add any attributes
	if ( ! empty( $data['attributes'] ) && is_array( $data['attributes'] ) ) {
		foreach ( $data['attributes'] as $attribute_key => $attribute_value ) {
			$element->setAttribute( $attribute_key, $attribute_value );
		}
	}

	// Any other items in the data array should be child elements
	foreach ( $data as $data_key => $child_data ) {
		if ( ! is_numeric( $data_key ) )
			continue;

		$child = generate_xml_element( $dom, $child_data );
		if ( $child )
			$element->appendChild( $child );
	}

	return $element;
}

$doc = new DOMDocument();
$child = generate_xml_element( $doc, $data );
if ( $child )
	$doc->appendChild( $child );
$doc->formatOutput = true; // Add whitespace to make easier to read XML
$xml = $doc->saveXML();

You first create a blank canvas by creating a new instance of the DOMDocument class and then you pass the class instance (needed for creating elements in the correct character set and such) and the data array to the generate_xml_element() function. This function will create the top level element and then recursively call itself on any child elements until it’s gone through the whole array.

Once it’s done, you’ll need to append the element to the DOM using the inherited appendChild() function. Then calling saveXML will give you the XML output. The above example data array will give you something like this (maybe or maybe not nicely formatted with whitespace depending on what mood DOMDocument is in):

<?xml version="1.0"?>
<toplevelelement foo="bar" fruit="apple">
	Some random value.
	<achildelement>Value</achildelement>
	<anotherchildelement some="attr">
		<grandchildelement></grandchildelement>
	</anotherchildelement>
</toplevelelement>

And there you have it!