Example usage:
$xmlNode = simplexml_load_file('example.xml');
$arrayData = xmlToArray($xmlNode);
echo json_encode($arrayData);
Read the blog post for more info.
License: Public domain
Example usage:
$xmlNode = simplexml_load_file('example.xml');
$arrayData = xmlToArray($xmlNode);
echo json_encode($arrayData);
Read the blog post for more info.
License: Public domain
<?php | |
/** | |
* Create plain PHP associative array from XML. | |
* | |
* Example usage: | |
* $xmlNode = simplexml_load_file('example.xml'); | |
* $arrayData = xmlToArray($xmlNode); | |
* echo json_encode($arrayData); | |
* | |
* @param SimpleXMLElement $xml The root node | |
* @param array $options Associative array of options | |
* @return array | |
* @link http://outlandishideas.co.uk/blog/2012/08/xml-to-json/ More info | |
* @author Tamlyn Rhodes <http://tamlyn.org> | |
* @license http://creativecommons.org/publicdomain/mark/1.0/ Public Domain | |
*/ | |
function xmlToArray($xml, $options = array()) { | |
$defaults = array( | |
'namespaceRecursive' => false, //setting to true will get xml doc namespaces recursively | |
'removeNamespace' => false, //set to true if you want to remove the namespace from resulting keys (recommend setting namespaceSeparator = '' when this is set to true) | |
'namespaceSeparator' => ':', //you may want this to be something other than a colon | |
'attributePrefix' => '@', //to distinguish between attributes and nodes with the same name | |
'alwaysArray' => array(), //array of xml tag names which should always become arrays | |
'autoArray' => true, //only create arrays for tags which appear more than once | |
'textContent' => '$', //key used for the text content of elements | |
'autoText' => true, //skip textContent key if node has no attributes or child nodes | |
'keySearch' => false, //optional search and replace on tag and attribute names | |
'keyReplace' => false //replace values for above search values (as passed to str_replace()) | |
); | |
$options = array_merge($defaults, $options); | |
$namespaces = $xml->getDocNamespaces($options['namespaceRecursive']); | |
$namespaces[''] = null; //add base (empty) namespace | |
//get attributes from all namespaces | |
$attributesArray = array(); | |
foreach ($namespaces as $prefix => $namespace) { | |
if ($options['removeNamespace']) { | |
$prefix = ''; | |
} | |
foreach ($xml->attributes($namespace) as $attributeName => $attribute) { | |
//replace characters in attribute name | |
if ($options['keySearch']) { | |
$attributeName = | |
str_replace($options['keySearch'], $options['keyReplace'], $attributeName); | |
} | |
$attributeKey = $options['attributePrefix'] | |
. ($prefix ? $prefix . $options['namespaceSeparator'] : '') | |
. $attributeName; | |
$attributesArray[$attributeKey] = (string)$attribute; | |
} | |
} | |
//get child nodes from all namespaces | |
$tagsArray = array(); | |
foreach ($namespaces as $prefix => $namespace) { | |
if ($options['removeNamespace']) { | |
$prefix = ''; | |
} | |
foreach ($xml->children($namespace) as $childXml) { | |
//recurse into child nodes | |
$childArray = xmlToArray($childXml, $options); | |
$childTagName = key($childArray); | |
$childProperties = current($childArray); | |
//replace characters in tag name | |
if ($options['keySearch']) { | |
$childTagName = | |
str_replace($options['keySearch'], $options['keyReplace'], $childTagName); | |
} | |
//add namespace prefix, if any | |
if ($prefix) { | |
$childTagName = $prefix . $options['namespaceSeparator'] . $childTagName; | |
} | |
if (!isset($tagsArray[$childTagName])) { | |
//only entry with this key | |
//test if tags of this type should always be arrays, no matter the element count | |
$tagsArray[$childTagName] = | |
in_array($childTagName, $options['alwaysArray'], true) || !$options['autoArray'] | |
? array($childProperties) : $childProperties; | |
} elseif ( | |
is_array($tagsArray[$childTagName]) && array_keys($tagsArray[$childTagName]) | |
=== range(0, count($tagsArray[$childTagName]) - 1) | |
) { | |
//key already exists and is integer indexed array | |
$tagsArray[$childTagName][] = $childProperties; | |
} else { | |
//key exists so convert to integer indexed array with previous value in position 0 | |
$tagsArray[$childTagName] = array($tagsArray[$childTagName], $childProperties); | |
} | |
} | |
} | |
//get text content of node | |
$textContentArray = array(); | |
$plainText = trim((string)$xml); | |
if ($plainText !== '') { | |
$textContentArray[$options['textContent']] = $plainText; | |
} | |
//stick it all together | |
$propertiesArray = !$options['autoText'] || $attributesArray || $tagsArray || ($plainText === '') | |
? array_merge($attributesArray, $tagsArray, $textContentArray) : $plainText; | |
//return node as array | |
return array( | |
$xml->getName() => $propertiesArray | |
); | |
} |