Convert XML to array and vice versa in PHP

As a developer, it is common to search the web for an existing (open source) code snippet to re-use for an application, but it is rare for the developer to just copy code online and use it straight in their application without modifying it first.

I am one of many developers who like to save time if possible by using open source code if coding from scratch takes longer than a couple of minutes, but there are times when one cannot be found. I ran into such situation when I wanted a function that converts an XML string into an array. Unfortunately, most are overly complicated for what I wanted, so I decided to create my own and share with the world. The following function converts XML strings into a PHP array while retaining the level depths of the XML but all attributes are ignored.

/**
 * Simple XML to array conversion.
 *
 * Warning: Ignores all attributes!
 *
 * Link: http://18.237.84.250/?p=79
 *
 * @author johnro
 * @param xml $string
 */
function convert_xml_to_array($string) {
	$parser = xml_parser_create();
	xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
	xml_parse_into_struct($parser, $string, $vals, $index);
	xml_parser_free($parser);

	$array = array();
	$curr = &$array;
	$levels = array();
	$item = array();
	foreach($vals as $val) {
		switch($val['type']) {
			case 'open':
				if(!empty($item)) {
					foreach($item as $key => $value) {
						$curr[$key] = $value;
					}
					$item = array();
				}
				$levels[$val['level']] = &$curr;
				$curr[$val['tag']] = array();
				$curr = &$curr[$val['tag']];
				break;
			case 'complete':
				$item[$val['tag']] = $val['value'];
				break;
			case 'close':
				if(!empty($item)) {
					foreach($item as $key => $value) {
						$curr[$key] = $value;
					}
					$item = array();
				}
				$curr = &$levels[$val['level']];

				break;
		}
	}

	return $array;
}

The following is a sample XML:



    Everyone
    John
    Test
    
		cool
		
			cat
			dog
			
				piano
				flute
			
		
	

which gets converted to the following array

array (
  'note' => 
  array (
    'to' => 'Everyone',
    'from' => 'John',
    'heading' => 'Test',
    'other' => 
    array (
      'type' => 'cool',
      'words' => 
      array (
        'first' => 'cat',
        'second' => 
        array (
        ),
      ),
    ),
  ),
)

To complete this library, I have also included a function to convert the array back to XML string.

/**
 * Simple array to XML conversion.
 *
 * Warning: Ignores all attributes!
 *
 * Link: http://18.237.84.250/?p=79
 *
 * @author johnro
 * @param array $array
 * @param string $namespace
 */
function convert_array_to_xml($array, $namespace = '') {
	$xml = '';
	foreach($array as $key => $value) {
		if(is_array($value)) {
			$value = convert_array_to_xml($value);
		}
		$xml .= "$value";
	}
	
	return $xml;
}

Feel free to use and any word of advice is appreciated.

Comments

2 responses to “Convert XML to array and vice versa in PHP”

  1. rubo77 Avatar

    i enhanced it a bit:

    /**
    * Simple array to XML conversion.
    *
    * Warning: Ignores all attributes!
    *
    * Link: http://18.237.84.250/?p=79
    *
    * @author johnro
    * @param array $array
    * @param string $namespace
    */
    function array2xml($array, $depth=0, $namespace = ”) {
    $nl=”
    “;
    $tab=” “;
    $xml = ”;
    foreach($array as $key => $value) {
    if(is_array($value)) {
    $value = array2xml($value,$depth+1);
    }
    if(is_numeric($key)){
    $key_start=’item nr=”‘.$key.’”‘;
    $key_end=’item’;
    }else {
    $key_start=$key;
    $key_end=$key;
    }
    if(isset($value[0]) and $value[0]=='<') {
    // childnote:
    $xml .= $nl.str_repeat($tab,$depth)."” . $nl.str_repeat($tab,$depth+1) . ($value) . $nl . str_repeat($tab,$depth) . “”;
    } else $xml .= $nl.str_repeat($tab,$depth).”” . XMLStrFormat($value) . “”;
    }

    return trim($xml);
    }

    function XMLStrFormat($str){
    /* In XML gilt wie in HTML: Zeichen, die bei der XML-Syntax besondere Bedeutung haben,
    müssen Sie umschreiben, wenn Sie sie im normalen Text zwischen den Tags verwenden wollen.
    Folgende Zeichen sind betroffen:
    Zeichen Notation in XML
    >
    & &
    ” "
    ‘ '

    */
    $str = str_replace(“&”, “&”, $str);
    $str = str_replace(“”, “>”, $str);
    $str = str_replace(“‘”, “'”, $str);
    $str = str_replace(“””, “"”, $str);
    $str = str_replace(”
    “, “”, $str);
    // xml generates an error for some characters below Ascii(32) (space):
    $str = str_replace(chr(11), “”, $str);
    $str = strtr($str,$GLOBALS[‘asc2uni’]);
    return $str;
    }

    $GLOBALS[‘asc2uni’] = Array();
    for($i=128;$i<256;$i++){
    $GLOBALS['asc2uni'][chr($i)] = "&#x".dechex($i).";";
    }

    Like

Leave a reply to rubo77 Cancel reply