How to convert array to SimpleXML

PhpXmlArraysSimplexml

Php Problem Overview


How can I convert an array to a SimpleXML object in PHP?

Php Solutions


Solution 1 - Php

Here is php 5.2 code which will convert array of any depth to xml document:

Array
(
    ['total_stud']=> 500
	[0] => Array
        (
            [student] => Array
                (
                    [id] => 1
                    [name] => abc
					[address] => Array
						(
							[city]=>Pune
							[zip]=>411006
						)						
                )
        )
    [1] => Array
        (
            [student] => Array
                (
                    [id] => 2
                    [name] => xyz
					[address] => Array
						(
							[city]=>Mumbai
							[zip]=>400906
						)	
                )
				
        )
)

generated XML would be as:

<?xml version="1.0"?>
<student_info>
	<total_stud>500</total_stud>
	<student>
		<id>1</id>
		<name>abc</name>
		<address>
			<city>Pune</city>
			<zip>411006</zip>
		</address>
	</student>
	<student>
		<id>1</id>
		<name>abc</name>
		<address>
			<city>Mumbai</city>
			<zip>400906</zip>
		</address>
	</student>
</student_info>

PHP snippet

<?php
// function defination to convert array to xml
function array_to_xml( $data, &$xml_data ) {
	foreach( $data as $key => $value ) {
		if( is_array($value) ) {
			if( is_numeric($key) ){
                $key = 'item'.$key; //dealing with <0/>..<n/> issues
			}
			$subnode = $xml_data->addChild($key);
			array_to_xml($value, $subnode);
		} else {
			$xml_data->addChild("$key",htmlspecialchars("$value"));
		}
	 }
}
      
// initializing or creating array
$data = array('total_stud' => 500);

// creating object of SimpleXMLElement
$xml_data = new SimpleXMLElement('<?xml version="1.0"?><data></data>');

// function call to convert array to xml
array_to_xml($data,$xml_data);

//saving generated xml file; 
$result = $xml_data->asXML('/file/path/name.xml');

?>

Documentation on SimpleXMLElement::asXML used in this snippet

Solution 2 - Php

a short one:

<?php

$test_array = array (
  'bla' => 'blub',
  'foo' => 'bar',
  'another_array' => array (
    'stack' => 'overflow',
  ),
);
$xml = new SimpleXMLElement('<root/>');
array_walk_recursive($test_array, array ($xml, 'addChild'));
print $xml->asXML();

results in

<?xml version="1.0"?>
<root>
  <blub>bla</blub>
  <bar>foo</bar>
  <overflow>stack</overflow>
</root>

keys and values are swapped - you could fix that with array_flip() before the array_walk. array_walk_recursive requires PHP 5. you could use array_walk instead, but you won't get 'stack' => 'overflow' in the xml then.

Solution 3 - Php

The answers provided here only convert array to XML with nodes, you are not able to set attributes. I have written a php function that allows you to convert an array to php and also set attributes for particular nodes in the xml. The downside here is you have to construct an array in a particular way with few conventions (only if you want to use attributes)

The following example will allow you to set attributes in XML too.

The source can be found here: https://github.com/digitickets/lalit/blob/master/src/Array2XML.php

<?php    
$books = array(
    '@attributes' => array(
        'type' => 'fiction'
    ),
    'book' => array(
        array(
            '@attributes' => array(
                'author' => 'George Orwell'
            ),
            'title' => '1984'
        ),
        array(
            '@attributes' => array(
                'author' => 'Isaac Asimov'
            ),
            'title' => 'Foundation',
            'price' => '$15.61'
        ),
        array(
            '@attributes' => array(
                'author' => 'Robert A Heinlein'
            ),
            'title' => 'Stranger in a Strange Land',
            'price' => array(
                '@attributes' => array(
                    'discount' => '10%'
                ),
                '@value' => '$18.00'
            )
        )
    )
);
/* creates 
<books type="fiction">
  <book author="George Orwell">
    <title>1984</title>
  </book>
  <book author="Isaac Asimov">
    <title>Foundation</title>
    <price>$15.61</price>
  </book>
  <book author="Robert A Heinlein">
    <title>Stranger in a Strange Land</title>
    <price discount="10%">$18.00</price>
  </book>
</books>
*/
?>

Solution 4 - Php

I found all of the answers to use too much code. Here is an easy way to do it:

function to_xml(SimpleXMLElement $object, array $data)
{   
    foreach ($data as $key => $value) {
        if (is_array($value)) {
            $new_object = $object->addChild($key);
            to_xml($new_object, $value);
        } else {
            // if the key is an integer, it needs text with it to actually work.
            if ($key != 0 && $key == (int) $key) {
                $key = "key_$key";
            }

            $object->addChild($key, $value);
        }   
    }   
}   

Then it's a simple matter of sending the array into the function, which uses recursion, so it will handle a multi-dimensional array:

$xml = new SimpleXMLElement('<rootTag/>');
to_xml($xml, $my_array);

Now $xml contains a beautiful XML object based on your array exactly how you wrote it.

print $xml->asXML();

Solution 5 - Php

<?php
function array_to_xml(array $arr, SimpleXMLElement $xml)
{
foreach ($arr as $k => $v) {
is_array($v)
? array_to_xml($v, $xml->addChild($k))
: $xml->addChild($k, $v);
}
return $xml;
}

$test_array = array ( 'bla' => 'blub', 'foo' => 'bar', 'another_array' => array ( 'stack' => 'overflow', ), );

echo array_to_xml($test_array, new SimpleXMLElement('<root/>'))->asXML();

Solution 6 - Php

From PHP 5.4

function array2xml($data, $root = null){
    $xml = new SimpleXMLElement($root ? '<' . $root . '/>' : '<root/>');
    array_walk_recursive($data, function($value, $key)use($xml){
        $xml->addChild($key, $value);
    });
    return $xml->asXML();
}

Solution 7 - Php

Another improvement:

/**
* Converts an array to XML
*
* @param array $array
* @param SimpleXMLElement $xml
* @param string $child_name
*
* @return SimpleXMLElement $xml
*/
public function arrayToXML($array, SimpleXMLElement $xml, $child_name)
{
    foreach ($array as $k => $v) {
        if(is_array($v)) {
            (is_int($k)) ? $this->arrayToXML($v, $xml->addChild($child_name), $v) : $this->arrayToXML($v, $xml->addChild(strtolower($k)), $child_name);
        } else {
            (is_int($k)) ? $xml->addChild($child_name, $v) : $xml->addChild(strtolower($k), $v);
        }
    }

    return $xml->asXML();
}

Usage:

$this->arrayToXML($array, new SimpleXMLElement('<root/>'), 'child_name_to_replace_numeric_integers');

Solution 8 - Php

Here is my entry, simple and clean..

function array2xml($array, $xml = false){
	if($xml === false){
		$xml = new SimpleXMLElement('<root/>');
	}
	foreach($array as $key => $value){
		if(is_array($value)){
			array2xml($value, $xml->addChild($key));
		}else{
			$xml->addChild($key, $value);
		}
	}
	return $xml->asXML();
}


header('Content-type: text/xml');
print array2xml($array);

Solution 9 - Php

So anyway... I took onokazu's code (thanks!) and added the ability to have repeated tags in XML, it also supports attributes, hope someone finds it useful!

 <?php
    
function array_to_xml(array $arr, SimpleXMLElement $xml) {
		foreach ($arr as $k => $v) {
			
			$attrArr = array();
			$kArray = explode(' ',$k);
			$tag = array_shift($kArray);
			
			if (count($kArray) > 0) {
				foreach($kArray as $attrValue) {
					$attrArr[] = explode('=',$attrValue);					
				}
			}
			
			if (is_array($v)) {
				if (is_numeric($k)) {
					array_to_xml($v, $xml);
				} else {
					$child = $xml->addChild($tag);
					if (isset($attrArr)) {
						foreach($attrArr as $attrArrV) {
							$child->addAttribute($attrArrV[0],$attrArrV[1]);
						}
					}					
					array_to_xml($v, $child);
				}
			} else {
				$child = $xml->addChild($tag, $v);
				if (isset($attrArr)) {
					foreach($attrArr as $attrArrV) {
						$child->addAttribute($attrArrV[0],$attrArrV[1]);
					}
				}
			}				
		}
		
		return $xml;
	}
    
    	$test_array = array (
    	  'bla' => 'blub',
    	  'foo' => 'bar',
    	  'another_array' => array (
    		array('stack' => 'overflow'),
    		array('stack' => 'overflow'),
    		array('stack' => 'overflow'),
    	  ),
    	  'foo attribute1=value1 attribute2=value2' => 'bar',
    	);	
    
    	$xml = array_to_xml($test_array, new SimpleXMLElement('<root/>'))->asXML();
    
    	echo "$xml\n";
    	$dom = new DOMDocument;
    	$dom->preserveWhiteSpace = FALSE;
    	$dom->loadXML($xml);
    	$dom->formatOutput = TRUE;
    	echo $dom->saveXml();
    ?>

Solution 10 - Php

I wanted a code that will take all the elements inside an array and treat them as attributes, and all arrays as sub elements.

So for something like

array (
'row1' => array ('head_element' =>array("prop1"=>"some value","prop2"=>array("empty"))),
"row2"=> array ("stack"=>"overflow","overflow"=>"overflow")
);

I would get something like this

<?xml version="1.0" encoding="utf-8"?>
<someRoot>
  <row1>
    <head_element prop1="some value">
      <prop2 0="empty"/>
    </head_element>
  </row1>
  <row2 stack="overflow" overflow="stack"/>
 </someRoot>

To achive this the code is below, but be very careful, it is recursive and may actually cause a stackoverflow :)

function addElements(&$xml,$array)
{
$params=array();
foreach($array as $k=>$v)
{
	if(is_array($v))
		addElements($xml->addChild($k), $v);
	else $xml->addAttribute($k,$v);
}

}
function xml_encode($array)
{
if(!is_array($array))
	trigger_error("Type missmatch xml_encode",E_USER_ERROR);
$xml=new SimpleXMLElement('<?xml version=\'1.0\' encoding=\'utf-8\'?><'.key($array).'/>');
addElements($xml,$array[key($array)]);
return $xml->asXML();
} 

You may want to add checks for length of the array so that some element get set inside the data part and not as an attribute.

Solution 11 - Php

I use a couple of functions that I wrote a while back to generate the xml to pass back and forth from PHP and jQuery etc... Neither use any additional frameworks just purely generates a string that can then be used with SimpleXML (or other framework)...

If it's useful to anyone, please use it :)

function generateXML($tag_in,$value_in="",$attribute_in=""){
	$return = "";
	$attributes_out = "";
	if (is_array($attribute_in)){
		if (count($attribute_in) != 0){
			foreach($attribute_in as $k=>$v):
				$attributes_out .= " ".$k."=\"".$v."\"";
			endforeach;
		}
	}
	return "<".$tag_in."".$attributes_out.((trim($value_in) == "") ? "/>" : ">".$value_in."</".$tag_in.">" );
}

function arrayToXML($array_in){
	$return = "";
	$attributes = array();
	foreach($array_in as $k=>$v):
		if ($k[0] == "@"){
			// attribute...
			$attributes[str_replace("@","",$k)] = $v;
		} else {
			if (is_array($v)){
				$return .= generateXML($k,arrayToXML($v),$attributes);
				$attributes = array();
			} else if (is_bool($v)) {
				$return .= generateXML($k,(($v==true)? "true" : "false"),$attributes);
				$attributes = array();
			} else {
				$return .= generateXML($k,$v,$attributes);
				$attributes = array();
			}
		}
	endforeach;
	return $return;
}	

Love to all :)

Solution 12 - Php

You could use the XMLParser that I have been working on.

$xml = XMLParser::encode(array(
    'bla' => 'blub',
    'foo' => 'bar',
    'another_array' => array (
        'stack' => 'overflow',
    )
));
// @$xml instanceof SimpleXMLElement
echo $xml->asXML();

Would result in:

<?xml version="1.0"?>
<root>
    <bla>blub</bla>
    <foo>bar</foo>
    <another_array>
        <stack>overflow</stack>
    </another_array>
</root>

Solution 13 - Php

Based on everything else here, handles numerical indices + attributes via prefixing with @, and could inject xml to existing nodes:

Code

function simple_xmlify($arr, SimpleXMLElement $root = null, $el = 'x') {
	// based on, among others http://stackoverflow.com/a/1397164/1037948
	
	if(!isset($root) || null == $root) $root = new SimpleXMLElement('<' . $el . '/>');

	if(is_array($arr)) {
		foreach($arr as $k => $v) {
			// special: attributes
			if(is_string($k) && $k[0] == '@') $root->addAttribute(substr($k, 1),$v);
			// normal: append
			else simple_xmlify($v, $root->addChild(
					// fix 'invalid xml name' by prefixing numeric keys
					is_numeric($k) ? 'n' . $k : $k)
				);
		}
	} else {
		$root[0] = $arr;
	}

	return $root;
}//--	fn	simple_xmlify

Usage

// lazy declaration via "queryparam"
$args = 'hello=4&var[]=first&var[]=second&foo=1234&var[5]=fifth&var[sub][]=sub1&var[sub][]=sub2&var[sub][]=sub3&var[@name]=the-name&var[@attr2]=something-else&var[sub][@x]=4.356&var[sub][@y]=-9.2252';
$q = array();
parse_str($val, $q);

$xml = simple_xmlify($q); // dump $xml, or...
$result = get_formatted_xml($xml); // see below

Result

<?xml version="1.0"?>
<x>
  <hello>4</hello>
  <var name="the-name" attr2="something-else">
    <n0>first</n0>
    <n1>second</n1>
    <n5>fifth</n5>
    <sub x="4.356" y="-9.2252">
      <n0>sub1</n0>
      <n1>sub2</n1>
      <n2>sub3</n2>
    </sub>
  </var>
  <foo>1234</foo>
</x>

Bonus: Formatting XML

function get_formatted_xml(SimpleXMLElement $xml, $domver = null, $preserveWhitespace = true, $formatOutput = true) {
	// http://stackoverflow.com/questions/1191167/format-output-of-simplexml-asxml

	// create new wrapper, so we can get formatting options
	$dom = new DOMDocument($domver);
	$dom->preserveWhiteSpace = $preserveWhitespace;
	$dom->formatOutput = $formatOutput;
	// now import the xml (converted to dom format)
	/*
	$ix = dom_import_simplexml($xml);
	$ix = $dom->importNode($ix, true);
	$dom->appendChild($ix);
	*/
	$dom->loadXML($xml->asXML());
	
	// print
	return $dom->saveXML();
}//--	fn	get_formatted_xml

Solution 14 - Php

IF the array is associative and keyed correctly, it would probably be easier to turn it into xml first. Something like:

  function array2xml ($array_item) {
	$xml = '';
	foreach($array_item as $element => $value)
	{
		if (is_array($value))
		{
			$xml .= "<$element>".array2xml($value)."</$element>";
		}
		elseif($value == '')
		{
			$xml .= "<$element />";
		}
		else
		{
			$xml .= "<$element>".htmlentities($value)."</$element>";
		}
	}
	return $xml;
}

$simple_xml = simplexml_load_string(array2xml($assoc_array));

The other route would be to create your basic xml first, like

$simple_xml = simplexml_load_string("<array></array>");

and then for each part of your array, use something similar to my text creating loop and instead use the simplexml functions "addChild" for each node of the array.

I'll try that out later and update this post with both versions.

Solution 15 - Php

Here's a function that did the trick for me:

Just call it with something like

echo arrayToXml("response",$arrayIWantToConvert);
function arrayToXml($thisNodeName,$input){
		if(is_numeric($thisNodeName))
			throw new Exception("cannot parse into xml. remainder :".print_r($input,true));
		if(!(is_array($input) || is_object($input))){
			return "<$thisNodeName>$input</$thisNodeName>";
		}
		else{
			$newNode="<$thisNodeName>";
			foreach($input as $key=>$value){
				if(is_numeric($key))
					$key=substr($thisNodeName,0,strlen($thisNodeName)-1);
				$newNode.=arrayToXml3($key,$value);
			}
			$newNode.="</$thisNodeName>";
			return $newNode;
		}
	}

Solution 16 - Php

I found this solution similar to the original problem

<?php

$test_array = array (
  'bla' => 'blub',
  'foo' => 'bar',
  'another_array' => array (
    'stack' => 'overflow',
  ),
);

class NoSimpleXMLElement extends SimpleXMLElement {
 public function addChild($name,$value) {
  parent::addChild($value,$name);
 }
}
$xml = new NoSimpleXMLElement('<root/>');
array_walk_recursive($test_array, array ($xml, 'addChild'));
print $xml->asXML();

Solution 17 - Php

Most of the above answers are correct. However, I came up with this answer which solves the array_walk_recursive compatibility issue and also the numerical keys problem. It also passed all the tests I made:

function arrayToXML(Array $array, SimpleXMLElement &$xml) {

    foreach($array as $key => $value) {
	
	    // None array
	    if (!is_array($value)) {
		    (is_numeric($key)) ? $xml->addChild("item$key", $value) : $xml->addChild($key, $value);
		    continue;
	    }	
		
	    // Array
	    $xmlChild = (is_numeric($key)) ? $xml->addChild("item$key") : $xml->addChild($key);
	    arrayToXML($value, $xmlChild);
    }
}	

I have also added a test class for this which you may find useful:

class ArrayToXmlTest extends PHPUnit_Framework_TestCase {
    
    public function setUp(){ }
  	public function tearDown(){ }
    
    public function testFuncExists() {
        $this->assertTrue(function_exists('arrayToXML'));
    }

    public function testFuncReturnsXml() {
        $array = array(
        	'name' => 'ardi',
        	'last_name' => 'eshghi',
        	'age' => 31,
        	'tel' => '0785323435'
        );

        $xmlEl =  new SimpleXMLElement('<root/>');
        arrayToXml($array, $xmlEl);

        $this->assertTrue($xmlEl instanceOf SimpleXMLElement);
    }

    public function testAssocArrayToXml() {
   	    
   	    $array = array(
        	'name' => 'ardi',
        	'last_name' => 'eshghi',
        	'age' => 31,
        	'tel' => '0785323435'
        );

    	$expectedXmlEl = new SimpleXMLElement('<root/>'); 
    	$expectedXmlEl->addChild('name', $array['name']);
    	$expectedXmlEl->addChild('last_name', $array['last_name']);
    	$expectedXmlEl->addChild('age', $array['age']);
    	$expectedXmlEl->addChild('tel', $array['tel']);
        
        $actualXmlEl =  new SimpleXMLElement('<root/>');
        arrayToXml($array, $actualXmlEl);

        $this->assertEquals($expectedXmlEl->asXML(), $actualXmlEl->asXML());
    }

    public function testNoneAssocArrayToXml() {
   	    
   	    $array = array(
        	'ardi',
        	'eshghi',
        	31,
        	'0785323435'
        );

    	// Expected xml value
    	$expectedXmlEl = new SimpleXMLElement('<root/>'); 
    	foreach($array as $key => $value)
    		$expectedXmlEl->addChild("item$key", $value);

		// What the function produces    	
        $actualXmlEl =  new SimpleXMLElement('<root/>');
        arrayToXml($array, $actualXmlEl);

        $this->assertEquals($expectedXmlEl->asXML(), $actualXmlEl->asXML());
    }

    public function testNestedMixArrayToXml() {
   	    
   	    $testArray = array(
			"goal",
			"nice",
			"funny" => array(
				'name' => 'ardi',
				'tel'	=>'07415517499',
				"vary",
				"fields" => array(
					'small',
					'email' => '[email protected]'
				),

				'good old days'

			),

			"notes" => "come on lads lets enjoy this",
			"cast" => array(
				'Tom Cruise',
				'Thomas Muller' => array('age' => 24)
			)
		);

    	// Expected xml value
    	$expectedXmlEl = new SimpleXMLElement('<root/>'); 
    	$expectedXmlEl->addChild('item0', $testArray[0]);
    	$expectedXmlEl->addChild('item1', $testArray[1]);
    	$childEl = $expectedXmlEl->addChild('funny');
    	$childEl->addChild("name", $testArray['funny']['name']);
    	$childEl->addChild("tel", $testArray['funny']['tel']);
    	$childEl->addChild("item0", "vary");
    	$childChildEl = $childEl->addChild("fields");
    	$childChildEl->addChild('item0', 'small');
    	$childChildEl->addChild('email', $testArray['funny']['fields']['email']);
    	$childEl->addChild("item1", 'good old days');
    	$expectedXmlEl->addChild('notes', $testArray['notes']);
    	$childEl2 = $expectedXmlEl->addChild('cast');
    	$childEl2->addChild('item0', 'Tom Cruise');
    	$childChildEl2 = $childEl2->addChild('Thomas Muller');
    	$childChildEl2->addChild('age', $testArray['cast']['Thomas Muller']['age']);

		// What the function produces    	
        $actualXmlEl = new SimpleXMLElement('<root/>');
        arrayToXml($testArray, $actualXmlEl);

        $this->assertEquals($expectedXmlEl->asXML(), $actualXmlEl->asXML());
    }
}      

Solution 18 - Php

other solution:

$marray=array(....);
$options = array(
                "encoding" => "UTF-8",
				"output_type" => "xml", 
				"version" => "simple",
				"escaping" => array("non-ascii, on-print, markup")
				);
$xmlres = xmlrpc_encode_request('root', $marray, $options);
print($xmlres);

Solution 19 - Php

Just a edit on a function above, when a key is numeric, add a prefix "key_"

// initializing or creating array
$student_info = array(your array data);

// creating object of SimpleXMLElement
$xml_student_info = new SimpleXMLElement("<?xml version=\"1.0\"?><student_info></student_info>");

// function call to convert array to xml
array_to_xml($student,$xml_student_info);

//saving generated xml file
$xml_student_info->asXML('file path and name');


function array_to_xml($student_info, &$xml_student_info) {
     foreach($student_info as $key => $value) {
          if(is_array($value)) {
            if(!is_numeric($key)){
                $subnode = $xml_student_info->addChild("$key");
                array_to_xml($value, $subnode);
            }
            else{
                $subnode = $xml_student_info->addChild("key_$key");
                array_to_xml($value, $subnode);
            }
          }
          else {
               if(!is_numeric($key)){
                    $xml_student_info->addChild("$key","$value");
               }else{
                    $xml_student_info->addChild("key_$key","$value");
               }
          }
     }
}

Solution 20 - Php

You can Use the following function in you code directly,

    function artoxml($arr, $i=1,$flag=false){
    $sp = "";
    for($j=0;$j<=$i;$j++){
        $sp.=" ";
     }
    foreach($arr as $key=>$val){
        echo "$sp&lt;".$key."&gt;";
        if($i==1) echo "\n";
        if(is_array($val)){
            if(!$flag){echo"\n";}
            artoxml($val,$i+5);
            echo "$sp&lt;/".$key."&gt;\n";
        }else{
              echo "$val"."&lt;/".$key."&gt;\n";
         }
    }
    
}

Call the function with first argument as your array and the second argument must be 1, this will be increased for perfect indentation, and third must be true.

for example, if the array variable to be converted is $array1 then, calling would be, the calling function should be encapsulated with <pre> tag.

  artoxml($array1,1,true);   

Please see the page source after executing the file, because the < and > symbols won't be displayed in a html page.

Solution 21 - Php

function toXML($data, $obj = false, $dom) {
	$is_first_level = false;
	if($obj === false) {
		$dom = new DomDocument('1.0');
		$obj = $dom;
		$is_first_level = true;
	}

	if(is_array($data)) {
		foreach($data as $key => $item) {
			$this->toXML($item, $obj->appendChild($dom->createElement($key)), $dom);
		}
	}else {
		$obj->appendChild($dom->createTextNode($data));
	}

	if($is_first_level) {
		$obj->formatOutput = true;
		return $obj->saveXML();
	}
	return $obj;
}

Solution 22 - Php

function array2xml(array $data, SimpleXMLElement $object = null, $oldNodeName = 'item')
{
	if (is_null($object)) $object = new SimpleXMLElement('<root/>');
	$isNumbered = true;
	$idx = 0;
	foreach ($data as $key => $x)
		if (is_string($key) || ($idx++ != $key + 0))
			$isNumbered = false;
	foreach ($data as $key => $value)
	{   
		$attribute = preg_match('/^[0-9]/', $key . '') ? $key : null;
		$key = (is_string($key) && !preg_match('/^[0-9]/', $key . '')) ? $key : preg_replace('/s$/', '', $oldNodeName);
		if (is_array($value))
		{
			$new_object = $object->addChild($key);
			if (!$isNumbered && !is_null($attribute)) $new_object->addAttribute('id', $attribute);
			array2xml($value, $new_object, $key);
		}
		else
		{
			if (is_bool($value)) $value = $value ? 'true' : 'false';
			$node = $object->addChild($key, htmlspecialchars($value));
			if (!$isNumbered && !is_null($attribute) && !isset($node->attributes()->id))
				$node->addAttribute('id', $attribute);
		}
	}
	return $object;
}

This function returns for example a list of <obj>...</obj><obj>...</obj> XML tags for numeric indexes.

Input:

	array(
	'people' => array(
		'dog',
		'cat',
		'life' => array(
			'gum',
			'shoe',
		),
		'fish',
	),
	array('yeah'),
)

Output:

<root>
	<people>
		<people>dog</people>
		<people>cat</people>
		<life>
			<life>gum</life>
			<life>shoe</life>
		</life>
		<people>fish</people>
		<people>
			<people>yeah</people>
		</people>
	</people>
</root>

This should satisfy all common needs. Maybe you may change the 3rd line to:

$key = is_string($key) ? $key : $oldNodeName . '_' . $key;

or if you are working with plurals ending with s:

$key = is_string($key) ? $key : preg_replace('/s$/', '', $oldNodeName);

Solution 23 - Php

With FluidXML you can generate, starting from a PHP Array, an XML for SimpleXML with... just two lines of code.

$fluidxml  = fluidxml($array);
$simplexml = simplexml_import_dom($fluidxml->dom());

An example array could be

$array = [ 'doc' => [              'fruit' => 'orange',              'cake'  => [                   '@id' => '123',                    '@'   => 'tiramisu' ],
              [ 'pasta' => 'matriciana' ],
              [ 'pasta' => 'boscaiola'  ]
] ];

https://github.com/servo-php/fluidxml

Solution 24 - Php

You may use xmlrpc_encode to create a xml from array if a verbose xml is not a problem. www.php.net/xmlrpc_encode

be careful the xml created differs in case you use associative and/or numeric keys

<?php
// /params/param/value/struct/member
// there is a tag "member" for each element
// "member" contains a tag "name". its value is the associative key
$xml1 = xmlrpc_encode(array('a'=>'b','c'=>'d'));
$simplexml1 = simplexml_load_string($xml1);
print_r($xml1);
print_r($simplexml1);

// /params/param/value/array/data
// there is a tag "data" for each element
// "data" doesn't contain the tag "name"
$xml2 = xmlrpc_encode(array('a','b'));
$simplexml2 = simplexml_load_string($xml2);
print_r($xml2);
print_r($simplexml2);
?>

Solution 25 - Php

function array2xml($array, $xml = false){
	
    if($xml === false){
    	
        $xml = new SimpleXMLElement('<?xml version=\'1.0\' encoding=\'utf-8\'?><'.key($array).'/>');
		$array = $array[key($array)];
		
    }
    foreach($array as $key => $value){
        if(is_array($value)){
            $this->array2xml($value, $xml->addChild($key));
        }else{
            $xml->addChild($key, $value);
        }
    }
    return $xml->asXML();
}

Solution 26 - Php

My answer, cobbling together others' answers. This should correct for the failure to compensate for numeric keys:

function array_to_xml($array, $root, $element) {
    $xml = new SimpleXMLElement("<{$root}/>");
    foreach ($array as $value) {
        $elem = $xml->addChild($element);
        xml_recurse_child($elem, $value);
    }
    return $xml;
}

function xml_recurse_child(&$node, $child) {
    foreach ($child as $key=>$value) {
        if(is_array($value)) {
            foreach ($value as $k => $v) {
                if(is_numeric($k)){
                    xml_recurse_child($node, array($key => $v));
                }
                else {
                    $subnode = $node->addChild($key);
                    xml_recurse_child($subnode, $value);
                }
            }
        }
        else {
            $node->addChild($key, $value);
        }
    }	
}

The array_to_xml() function presumes that the array is made up of numeric keys first. If your array had an initial element, you would drop the foreach() and $elem statements from the array_to_xml() function and just pass $xml instead.

Solution 27 - Php

I would have commented the second most voted answer, because it doesn't preserve structure and generates bad xml if there is numerically indexed inner arrays.

I developed my own version based on it, because I needed simple converter between json and xml regardless of the structure of data. My version preserves numeric key information and structure of the original array. It creates elements for the numerically indexed values by wrapping values to value -named elements with key-attribute that contains numerical key.

For example

array('test' => array(0 => 'some value', 1 => 'other'))

converts to

<test><value key="0">some value</value><value key="1">other</value></test>

My version of array_to_xml -function (hope it helps somebody :)

function array_to_xml($arr, &$xml) {
	foreach($arr as $key => $value) {
		if(is_array($value)) {
			if(!is_numeric($key)){
				$subnode = $xml->addChild("$key");
			} else {
				$subnode = $xml->addChild("value");
				$subnode->addAttribute('key', $key);					
			}
			array_to_xml($value, $subnode);
		}
		else {
			if (is_numeric($key)) {
				$xml->addChild("value", $value)->addAttribute('key', $key);
			} else {
				$xml->addChild("$key",$value);
			}
		}
	}
}	

Solution 28 - Php

Whole XML structure is defined in $data Array:

function array2Xml($data, $xml = null)
{
	if (is_null($xml)) {
		$xml = simplexml_load_string('<' . key($data) . '/>');
		$data = current($data);
		$return = true;
	}
	if (is_array($data)) {
		foreach ($data as $name => $value) {
			array2Xml($value, is_numeric($name) ? $xml : $xml->addChild($name));
		}
	} else {
		$xml->{0} = $data;
	}
	if (!empty($return)) {
		return $xml->asXML();
	}
}

Solution 29 - Php

If you work in magento and you have this type of associative array

$test_array = array (
	'0' => array (
			'category_id' => '582',
			'name' => 'Surat',
			'parent_id' => '565',
			'child_id' => '567',
			'active' => '1',
			'level' => '6',
			'position' => '17'
	),

	'1' => array (
			'category_id' => '567', 
			'name' => 'test',
			'parent_id' => '0',
			'child_id' => '576',
			'active' => '0',
			'level' => '0',
			'position' => '18'
	),
);

then this is best to convert associative array to xml format.Use this code in controller file.

$this->loadLayout(false);
//header ("content-type: text/xml");
$this->getResponse()->setHeader('Content-Type','text/xml');
$this->renderLayout();

$clArr2xml = new arr2xml($test_array, 'utf-8', 'listdata');
$output = $clArr2xml->get_xml();
print $output; 

class arr2xml
{
var $array = array();
var $xml = '';
var $root_name = '';
var $charset = '';

public function __construct($array, $charset = 'utf-8', $root_name = 'root')
{
	header ("content-type: text/xml");
	$this->array = $array;
	$this->root_name = $root_name;
	$this->charset = $charset;

	if (is_array($array) && count($array) > 0) {
		$this->struct_xml($array);
		
	} else {
		$this->xml .= "no data";
	}
}

public function struct_xml($array)
{
	foreach ($array as $k => $v) {
		if (is_array($v)) {
			$tag = ereg_replace('^[0-9]{1,}', 'item', $k); // replace numeric key in array to 'data'
			$this->xml .= "<$tag>";
			$this->struct_xml($v);
			$this->xml .= "</$tag>";
		} else {
			$tag = ereg_replace('^[0-9]{1,}', 'item', $k); // replace numeric key in array to 'data'
			$this->xml .= "<$tag><![CDATA[$v]]></$tag>";
		}
	}
}

public function get_xml()
{
	
	$header = "<?xml version=\"1.0\" encoding=\"" . $this->charset . "\"?><" . $this->root_name . ">";
	$footer = "</" . $this->root_name . ">";

	return $header . $this->xml . $footer;
}
}

I hope it helps to all.

Solution 30 - Php

// Structered array for XML convertion.
$data_array = array(
  array(
    '#xml_tag' => 'a',
    '#xml_value' => '',
    '#tag_attributes' => array(
      array(
        'name' => 'a_attr_name',
        'value' => 'a_attr_value',
      ),
    ),
    '#subnode' => array(
      array(
        '#xml_tag' => 'aa',
        '#xml_value' => 'aa_value',
        '#tag_attributes' => array(
          array(
            'name' => 'aa_attr_name',
            'value' => 'aa_attr_value',
          ),
        ),
        '#subnode' => FALSE,
      ),
    ),
  ),
  array(
    '#xml_tag' => 'b',
    '#xml_value' => 'b_value',
    '#tag_attributes' => FALSE,
    '#subnode' => FALSE,
  ),
  array(
    '#xml_tag' => 'c',
    '#xml_value' => 'c_value',
    '#tag_attributes' => array(
      array(
        'name' => 'c_attr_name',
        'value' => 'c_attr_value',
      ),
      array(
        'name' => 'c_attr_name_1',
        'value' => 'c_attr_value_1',
      ),
    ),
    '#subnode' => array(
      array(
        '#xml_tag' => 'ca',  
        '#xml_value' => 'ca_value',
        '#tag_attributes' => FALSE,
        '#subnode' => array(
          array(
            '#xml_tag' => 'caa',
            '#xml_value' => 'caa_value',
            '#tag_attributes' => array(
              array(
                'name' => 'caa_attr_name',
                'value' => 'caa_attr_value',
              ),
            ),
            '#subnode' => FALSE,
          ),
        ),
      ),
    ),
  ),
);


// creating object of SimpleXMLElement
$xml_object = new SimpleXMLElement('<?xml version=\"1.0\"?><student_info></student_info>');


// function call to convert array to xml
array_to_xml($data_array, $xml_object);

// saving generated xml file
$xml_object->asXML('/tmp/test.xml');

/**
 * Converts an structured PHP array to XML.
 *
 * @param Array $data_array
 *   The array data for converting into XML.
 * @param Object $xml_object
 *   The SimpleXMLElement Object
 *
 * @see https://gist.github.com/drupalista-br/9230016
 * 
 */
function array_to_xml($data_array, &$xml_object) {
  foreach($data_array as $node) {
    $subnode = $xml_object->addChild($node['#xml_tag'], $node['#xml_value']);

    if ($node['#tag_attributes']) {
      foreach ($node['#tag_attributes'] as $tag_attributes) {
        $subnode->addAttribute($tag_attributes['name'], $tag_attributes['value']); 
      }
    }

    if ($node['#subnode']) {
      array_to_xml($node['#subnode'], $subnode);
    }
  }
}

Solution 31 - Php

You can do this through DOM also. Please see below code.

<?php

$el = array();
$command = array();

$dom = new DOMDocument('1.0', 'utf-8');
$dom->formatOutput = true;

$xml_array = [
    'root'=>[
    'Good guy' => [
        'name' => [
            '_cdata' => 'Luke Skywalker'
        ],
        'weapon' => 'Lightsaber'
    ],
    'Bad guy' => [
        'name' => 'Sauron',
        'weapon' => 'Evil Eye'
    ]
        ]
];

convert_xml($xml_array);

if(!empty($el))
{
    $dom->appendChild(end($el));
}

echo $dom->saveXML();

?>

<?php

 function convert_xml($Xml)
{
    global $el, $dom;
    
        foreach($Xml as $id=>$val)
        {
            if(is_numeric($id))
            {
                $id = "Item".($id);
            }
            
            $id = str_replace(' ', '-', strtolower($id));
            
            if(is_array($val))
            {
                $ele = $dom->createElement($id);
                array_push($el, $ele);
                convert_xml($val);
            }
            else
            {
                $ele = $dom->createElement($id, $val);
                
                if(!empty($el))
                {
                    $com = end($el)->appendChild($ele);
                }
                else
                {
                    $dom->appendChild($ele);
                }
                
            }
        }
        
        if(sizeof($el) > 1)
        {
            $child = end($el);
            $com = prev($el)->appendChild($child);
            array_pop($el);
        }
}

?>

Solution 32 - Php

i think all the above solutions are nice but what i see so far, it not really creates an exact well formed XML because of ARRAY Keys with $my_array[main_node][multiple_values][] = array('id' => '1') are then converted into

    <main_node>
       <multiple_values>
         <0>
           <id>1 test</id>
         </0>
       </multiple_values>
       <multiple_values>
         <1>
          <id>2 test</id>
         </1>
       </multiple_values>
    </main_node>

which is a problem on a XML Parser side...

I should be like this:

    <main_node>
     <multiple_values>
      <id>1 test</id>
     </multiple_values>
     <multiple_values>
      <id>2 test</id>
     </multiple_values>
    </main_node>

So if you parse this by load_simple_xml...you will exactly the same array/object structure back.

My function also auto create the correct root node automatic.

    // Code to convert php array to xml document 20211112
	function array2xml(array $data, $xml_class_obj = '', $group_by_parent_allowed = '', $options = array())
		{   
			
			if(!$xml_class_obj) :
				$is_root = 1;
				$xml_class_obj = new XMLWriter();
				$xml_class_obj->openMemory();
				$xml_class_obj->setIndent(TRUE);
				$xml_class_obj->setIndentString('   ');
				if($options['encoding'] != '')	$xml_class_obj->startDocument('1.0', $options['encoding']);
				else														$xml_class_obj->startDocument('1.0');
			endif;
			
			foreach ($data as $key => $value) {

				if (is_array($value)) { // IS ARRAY

					// check if allow below keys are int, if yes group them to same parent tree
					$group_by_parent = $key;
					foreach(array_keys($value) as $c_keys) :
						if(!is_int($c_keys)) $group_by_parent = '';
					endforeach;

					if(empty($group_by_parent)) $xml_class_obj->startElement($key);	
					if($group_by_parent_allowed != '') $xml_class_obj->startElement($group_by_parent_allowed);
					
					$this->array2xml($value, $xml_class_obj, $group_by_parent, $options);
					
					if(empty($group_by_parent)) $xml_class_obj->endElement();  

				} else { // IS VALUE
					
					if(is_string($value)) :
						$xml_class_obj->startElement($key);
						$xml_class_obj->writeCData($value); 		
						$xml_class_obj->endElement();			
					else :
						$xml_class_obj->writeElement($key, $value); 
					endif;

				}

			} // foreach
			
			if($group_by_parent_allowed != '') 	$xml_class_obj->endElement(); 
			
			if($is_root == 1) :
			
				$xml_class_obj->endDocument();
				return $xml_class_obj->outputMemory();
			else :				
				return $xml_class_obj;					
			endif;
			  
		}  
    
    // usage
    $ary_new_xml = array();
	$ary_new_xml['order']['customer']['customerid'] = '123456'; 
	$ary_new_xml['order']['customer']['customertype'] = 15; 
			
	$ary_new_xml['order']['orderprio'] = 2; 
			
	$ary_new_xml['order']['orderpos'][] = array('sku' => 9999910001111, 'quantity' => 3); 			
	$ary_new_xml['order']['orderpos'][] = array('sku' => 9999910002222, 'quantity' => 1); 
			
echo array2xml($ary_new_xml,'','',array('enconding' => 'UTF-8'));

Results in:

<?xml version="1.0" encoding="UTF-8"?>
<order>
   <customer>
      <customerid>82936639</customerid>
      <customertype>15</customertype>
   </customer>
   <orderprio>2</orderprio>
   <orderpos>
      <sku>9999910001111</sku>
      <quantity>3</quantity>
   </orderpos>
   <orderpos>
      <sku>9999910002222</sku>
      <quantity>1</quantity>
   </orderpos>
</order>


 

I hope this helps somebody out there ;)

Solution 33 - Php

the following deals with namespaces. In this case, you construct the wrapper to include the namespace definitions, and pass it into the function. use a colon to identify the namespace.

Test Array

$inarray = [];
$inarray['p:apple'] = "red";
$inarray['p:pear'] = "green";
$inarray['p:peach'] = "orange";
$inarray['p1:grocers'] = ['p1:local' => "cheap", 'p1:imported' => "expensive"];


$xml = new SimpleXMLElement( '<p:wrapper xmlns:p="http://namespace.org/api" xmlns:p1="http://namespace.org/api2 /> ');

array_to_xml($xml,$inarray); 




function array_to_xml(SimpleXMLElement $object, array $data)
{   
	$nslist = $object->getDocNamespaces();
    
	foreach ($data as $key => $value)
    {   
		$nspace = null;
		$keyparts = explode(":",$key,2);
		if ( count($keyparts)==2) 
			$nspace = $nslist[$keyparts[0]];
			
		if (is_array($value))
        {   
            $key = is_numeric($key) ? "item$key" : $key;
			$new_object = $object->addChild($key,null,$nspace);
            array_to_xml($new_object, $value);
        }   
        else
        {   
            $key = is_numeric($key) ? "item$key" : $key;
			$object->addChild($key, $value,$nspace);
        }   
    }   
}   

Solution 34 - Php

You can use Mustache Template Engine and make a Template like:

{{#RECEIVER}}
<RECEIVER>
    <COMPANY>{{{COMPANY}}}</COMPANY>
    <CONTACT>{{{CONTACT}}}</CONTACT>
    <ADDRESS>{{{ADDRESS}}}</ADDRESS>
    <ZIP>{{ZIP}}</ZIP>
    <CITY>{{{CITY}}}</CITY>
</RECEIVER>
{{/RECEIVER}}
{{#DOC}}
<DOC>
    <TEXT>{{{TEXT}}}</TEXT>
    <NUMBER>{{{NUMBER}}}</NUMBER>
</DOC>
{{/DOC}}

Use it like this in PHP:

require_once( __DIR__ .'/../controls/Mustache/Autoloader.php' );
Mustache_Autoloader::register();
$oMustache = new Mustache_Engine();
$sTemplate = implode( '', file( __DIR__ ."/xml.tpl" ));
$return = $oMustache->render($sTemplate, $res);
echo($return);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMikeView Question on Stackoverflow
Solution 1 - PhpHanmantView Answer on Stackoverflow
Solution 2 - Phpax.View Answer on Stackoverflow
Solution 3 - PhpLalitView Answer on Stackoverflow
Solution 4 - PhpFrancis LewisView Answer on Stackoverflow
Solution 5 - PhponokazuView Answer on Stackoverflow
Solution 6 - Phpuser492589View Answer on Stackoverflow
Solution 7 - PhpSylView Answer on Stackoverflow
Solution 8 - PhpFrans van AsseltView Answer on Stackoverflow
Solution 9 - PhpCodePTView Answer on Stackoverflow
Solution 10 - PhplcorneaView Answer on Stackoverflow
Solution 11 - PhpNeil EnglishView Answer on Stackoverflow
Solution 12 - PhpjtrumbullView Answer on Stackoverflow
Solution 13 - PhpdrzausView Answer on Stackoverflow
Solution 14 - PhpAnthonyView Answer on Stackoverflow
Solution 15 - PhpmikeView Answer on Stackoverflow
Solution 16 - PhpcaiofiorView Answer on Stackoverflow
Solution 17 - PhpArdiView Answer on Stackoverflow
Solution 18 - PhpGaius BaltarView Answer on Stackoverflow
Solution 19 - PhpfrankeyView Answer on Stackoverflow
Solution 20 - PhpJosephVasantPrakashView Answer on Stackoverflow
Solution 21 - PhpAndreyView Answer on Stackoverflow
Solution 22 - Phpuser2381982View Answer on Stackoverflow
Solution 23 - PhpDaniele OrlandoView Answer on Stackoverflow
Solution 24 - Phpw35l3yView Answer on Stackoverflow
Solution 25 - PhpKamil DąbrowskiView Answer on Stackoverflow
Solution 26 - PhprefeydView Answer on Stackoverflow
Solution 27 - PhpJouni MäkeläinenView Answer on Stackoverflow
Solution 28 - PhpaceView Answer on Stackoverflow
Solution 29 - PhpBharat ChodvadiyaView Answer on Stackoverflow
Solution 30 - PhpFrancisco LuzView Answer on Stackoverflow
Solution 31 - Phpbhargav3vediView Answer on Stackoverflow
Solution 32 - PhpTomView Answer on Stackoverflow
Solution 33 - PhpsdwView Answer on Stackoverflow
Solution 34 - PhpKonstantin XFlash StratigenasView Answer on Stackoverflow