32

Variable $d comes from file_get_contents function to a URL.

$answer = @new SimpleXMLElement($d);

Below is output of the print_r($answer):

SimpleXMLElement Object
(
  [Amount] => 2698
  [Status] => OK
  [State] => FL
  [Country] => USA
)

How can I retrieve value of each element and add to an array? I can't figure it out.

Alessio Cantarella
  • 5,077
  • 3
  • 27
  • 34
Codex73
  • 5,690
  • 11
  • 56
  • 76

5 Answers5

64

In this simple case type casting will also work:

$my_array = (array)$answer
dkinzer
  • 32,179
  • 12
  • 66
  • 85
54

This should work:

$xml = simplexml_load_string($xmlstring);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
  • 1
    I just tested and this works. Even does it recursively, which is great. I do worry about what will happen in the event of a non-UTF-8 character, though. The `json_encode` and `json_decode` methods tend to choke when they come across a non-UTF-8 character. Wrapping in a `try...catch` would be wise, though I don't know if there would be a way to handle it properly (i.e. encode to UTF-8) without writing a custom parser. – Josh Mar 09 '15 at 22:53
  • 3
    Both `json_encode` and `http_build_query` seem to have issues interpreting `<![CDATA[` `]]>` tags. It seems both functions determine them to be empty objects, in which case `http_build_query` ignores it completely. – Shaun Cockerill Feb 08 '18 at 01:37
13

The $answer can already work as an array. You can do this if you want put it in a real array,

$array = array();
foreach($answer as $k => $v) {
  $array[$k] = $v;
}
Alessio Cantarella
  • 5,077
  • 3
  • 27
  • 34
ZZ Coder
  • 74,484
  • 29
  • 137
  • 169
8

I have a problem with this function because typecasting every XML child to an array can be problematic when the text is between CDATA tags.

I fixed this by checking if the result of the typecasting to an array is empty. If so typecast it to a string and you will get a proper result.

Here is my modified version with CDATA support:

function SimpleXML2ArrayWithCDATASupport($xml)
{   
    $array = (array)$xml;

    if (count($array) === 0) {
        return (string)$xml;
    }

    foreach ($array as $key => $value) {
        if (!is_object($value) || strpos(get_class($value), 'SimpleXML') === false) {
            continue;
        }
        $array[$key] = SimpleXML2ArrayWithCDATASupport($value);
    }

    return $array;
}
UnstableFractal
  • 1,403
  • 2
  • 15
  • 29
Bo Pennings
  • 945
  • 1
  • 10
  • 20
  • I found that `json_encode` and `http_build_query` suffer from the exact same symptoms, so this approach is the most reliable. – Shaun Cockerill Feb 08 '18 at 01:40
  • 1
    It's still ignoring CDATA fields. I had to do `$xml = simplexml_load_file('file.xml',SimpleXMLElement::class,LIBXML_NOCDATA);` but then your function wasn't needed anymore, I could just do `json_decode(json_encode((array) $xml),true);` – Rodrigo Jun 13 '21 at 02:54
  • Sadly, still doesn't work with namespace data :/ – Lukáš Klíma Mar 14 '22 at 14:18
1

this function parse a xml simpleXML recursive to array recursive

function SimpleXML2Array($xml){
    $array = (array)$xml;

    //recursive Parser
    foreach ($array as $key => $value){
        if(strpos(get_class($value),"SimpleXML")!==false){
            $array[$key] = SimpleXML2Array($value);
        }
    }

    return $array;
}
  • i have a problem with this function because typecasting every xml child to an array can give you a problem when the text is between CDATA tags. – Bo Pennings Jul 23 '14 at 19:56