Skip to content

Instantly share code, notes, and snippets.

@jasondmoss
Last active July 15, 2025 10:09
Show Gist options
  • Select an option

  • Save jasondmoss/7344311 to your computer and use it in GitHub Desktop.

Select an option

Save jasondmoss/7344311 to your computer and use it in GitHub Desktop.
Convert a SimpleXML object to associative array
<?php
/**
* Convert a SimpleXML object to an associative array
*
* @param object $xmlObject
*
* @return array
* @access public
*/
function simpleXmlToArray($xmlObject)
{
$array = [];
foreach ($xmlObject->children() as $node) {
$array[$node->getName()] = is_array($node) ? simplexml_to_array($node) : (string) $node;
}
return $array;
}
@carnini
Copy link

carnini commented Mar 12, 2021

Hi all, in the end, I used following from https://hotexamples.com/examples/-/-/simplexml_to_array/php-simplexml_to_array-function-examples.html, with some edits.

   /**
     * @param $xml
     * @return array
     * https://hotexamples.com/examples/-/-/simplexml_to_array/php-simplexml_to_array-function-examples.html
     */
    public static function simplexmlToArray($xml)
    {
        $ar = array();
        foreach ($xml->children() as $k => $v) {
            $child = self::simplexmlToArray($v);
            if (count($child) == 0) {
                $child = (string) $v;
            }
            foreach ($v->attributes() as $ak => $av) {
                if (!is_array($child)) {
                    $child = array("value" => $child);
                }
                $child[$ak] = (string) $av;
            }
            if (!array_key_exists($k, $ar)) {
                $ar[$k] = $child;
            } else {
                if (!is_string($ar[$k]) && isset($ar[$k][0])) {
                    $ar[$k][] = $child;
                } else {
                    $ar[$k] = array($ar[$k]);
                    $ar[$k][] = $child;
                }
            }
        }
        return $ar;
    }

This worked great, even on my XML that had many sub nodes.

@morawcik
Copy link

Hi all, in the end, I used following from https://hotexamples.com/examples/-/-/simplexml_to_array/php-simplexml_to_array-function-examples.html, with some edits.

   /**
     * @param $xml
     * @return array
     * https://hotexamples.com/examples/-/-/simplexml_to_array/php-simplexml_to_array-function-examples.html
     */
    public static function simplexmlToArray($xml)
    {
        $ar = array();
        foreach ($xml->children() as $k => $v) {
            $child = self::simplexmlToArray($v);
            if (count($child) == 0) {
                $child = (string) $v;
            }
            foreach ($v->attributes() as $ak => $av) {
                if (!is_array($child)) {
                    $child = array("value" => $child);
                }
                $child[$ak] = (string) $av;
            }
            if (!array_key_exists($k, $ar)) {
                $ar[$k] = $child;
            } else {
                if (!is_string($ar[$k]) && isset($ar[$k][0])) {
                    $ar[$k][] = $child;
                } else {
                    $ar[$k] = array($ar[$k]);
                    $ar[$k][] = $child;
                }
            }
        }
        return $ar;
    }

That works like a charm. Thanks!

@Harfusha
Copy link

Harfusha commented Oct 8, 2024

I refactored it to be more readable -> tested on php 8.3 + changed how attributes are stored

    /**
     * Converts a SimpleXMLElement object to an associative array.
     */
    public static function simpleXmlToArray(?SimpleXMLElement $xml): array|string {
        if ($xml === null) {
            return [];
        }

        $result = [];
        foreach ($xml->attributes() as $attrName => $attrValue) {
            $result['@attributes'][$attrName] = (string) $attrValue;
        }

        foreach ($xml->children() as $childName => $childElement) {
            $childArray = self::simpleXmlToArray($childElement);

            if (!isset($result[$childName])) {
                $result[$childName] = $childArray;
                continue;
            }

            if (!is_array($result[$childName]) || !array_is_list($result[$childName])) {
                $result[$childName] = [$result[$childName]];
            }

            $result[$childName][] = $childArray;
        }

        $textContent = trim((string) $xml);
        if (empty($result)) {
            return $textContent;
        }

        if ($textContent !== '') {
            $result['@value'] = $textContent;
        }

        return $result;
    }

@echavanon
Copy link

Thanx @Harfusha , saved me lot of time !

@adampatterson
Copy link

Will this give the expected result?

json_decode(json_encode($xml), true);

For the most part this worked for me, but I found some instances maybe 5 levels in that had CDATA content and were simply converted to an empty array.

@jasondmoss
Copy link
Author

Thanks everyone for chipping in to this simple little snippet (which worked for my purpose at the time). I mainly just use Gists as 'notes to self'. This has just kept growing :) Great job.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment