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!

21 thoughts on “Easily Create XML In PHP Using A Data Array

  1. I tried your creating an XML file from a PHP array. I used your example and could not the XML tree, only the values. I am probably missing something. I have been using PHP for over a dozen years, however this is the first time I tried to turn a PHP array in an XML output. If I ask real nice you assist me?

    I would like to take this sample array and turn it into a similar XML out as the example below.

    Array ( 
    	"zipcode" => "95610",
    	"city" => "Citrus Heights",
    	"icao" => "KMCC",
    	"ccobst" => "McClellan Airfield",
    	"obdist" => 7.3067011821565,
    	"oblat" => 38.667,
    	"oblong" => -121.4, 
    )
    <?xml version="1.0"?>
          <zipcode>95610</zipcode>
          <city>Citrus Heights</city>
          <icao>KMCC</icao>
          <ccobst>McClellan Airfield</ccobst>
          <obdist>7.3067011821565</obdist>
          <oblat>38.667</looblat>
          <oblong>-121.4</oblong>
    • With XML, I believe you need to have a single top level element to contain all of your data. Even if you don’t, my code requires one, so I made it “location”.

      $data = array(
      	'name' => 'location',
      	array(
      		'name' => 'zipcode',
      		'value'=> '95610',
      	),
      	array(
      		'name' => 'city',
      		'value'=> 'Citrus Heights',
      	),
      	array(
      		'name' => 'icao',
      		'value'=> 'KMCC',
      	),
      	array(
      		'name' => 'ccobst',
      		'value'=> 'McClellan Airfield',
      	),
      	array(
      		'name' => 'obdist',
      		'value'=> '7.3067011821565',
      	),
      	array(
      		'name' => 'oblat',
      		'value'=> '38.667',
      	),
      	array(
      		'name' => 'oblong',
      		'value'=> '-121.4',
      	),
      );
      <?xml version="1.0"?>
      <location>
      	<zipcode>95610</zipcode>
      	<city>Citrus Heights</city>
      	<icao>KMCC</icao>
      	<ccobst>McClellan Airfield</ccobst>
      	<obdist>7.3067011821565</obdist>
      	<oblat>38.667</oblat>
      	<oblong>-121.4</oblong>
      </location>
  2. Now the dumb question of the day; How do I get it to display as an XML tree like yours? I feel like such a novice today.

    Mine comes out as one long of only the values;

    95610Citrus HeightsKMCCMcClellan Airfield7.306701182156538.667-121.4

    <?xml version="1.0"?>
    <location>
        <zipcode>95610</zipcode>
        <city>Citrus Heights</city>
        <icao>KMCC</icao>
        <ccobst>McClellan Airfield</ccobst>
        <obdist>7.3067011821565</obdist>
        <oblat>38.667</oblat>
        <oblong>-121.4</oblong>
    </location>
    
  3. Hi, I need your help.

    xml file:

    ——————————————–

    This way you can print:

    STOKLAR->STOK as $stok) {
    foreach ($stok->OZELLIKLER as $ozellikler) {
    for ($i=0;$i <=count($ozellikler);$i++){

    echo '’ ;
    echo ” ;
    echo ”.$ozellikler->OZELLIK[$i].”;
    echo ‘:’;
    echo ”.$ozellikler->DEGER[$i].”;
    echo ” ;
    echo ” ;
    $i++;

    }
    }
    }

    ?>
    —————————————————-
    However, only the html table is added to the database, data is not added into HTML table cells.

    $xmlData = simplexml_load_file($xml_directory.$this->code.”/exaproperties.ashx”);
    foreach ($xmlData->STOKLAR->children() as $STOK) {
    foreach ($STOK->children() as $OZELLIKLER => $data) {
    for ($i=0;$i <=count($data);$i++){

    $tablo = '';
    $tablo.= '’ ;
    $tablo.= ” ;
    $tablo = ”.$data->OZELLIK[$i].”;
    $tablo.= ‘::’;
    $tablo.= ”.$data->DEGER[$i].”;
    $tablo.= ” ;
    $tablo.= ” ;
    }
    }
    }
    —————————————-
    If the support I rejoice.(Sorry for bad english)

  4. How do i generate a tree structure like a parent can have a child and that child can be a parent to another child

  5. I have this in one php file

    ‘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’,
    ),
    ),
    );

    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();

    ?>

    But I get white blank page only

  6. hi this post is obviously old but hope u can help me tweak your code a little – i need a further nested array to be allowed, but in your code, it exits if there is no ‘name’ tag at the next level.
    I need to allow the inner DEPENDENT array in this example:

    [2] => Array
    (
    [name] => Status
    [attributes] => Array
    (
    [Status] => Married
    )

    )

    [3] => Array
    (
    [0] => Array
    (
    [name] => Dependent
    [attributes] => Array
    (
    [Age] => 7
    )

    )

    [1] => Array
    (
    [name] => Dependent
    [attributes] => Array
    (
    [Age] => 3
    )

    )

    )

    Hope that makes sense and u can still help 🙂

Comments are closed.