8

Well I been having issues changing an xml back into an array....It would be simple if each xml followed the same format but every XML is different with the exception of the <Formula> tag, formulaname and movespeed ex:

<Formula>
<formulaname>Basic</formulaname>
<movespeed>1</movespeed>
<str>4</str>
<dex>3</dex>
<int>1</int>
<will>2</will>
</Formula>

or

<Formula>
<formulaname>Basic</formulaname>
<movespeed>1</movespeed>
<box>4</box>
<chicken>3</chicken>
<ducks>1</ducks>
<cereal>2</cereal>
</Formula>

What I have tried:

$xml = simplexml_load_file("test.xml");
print_r($xml);

This actually prints something but I couldn't get past that or even echo it..

foreach($xml->text as $string) { 
  print_r($string);
  echo 'attributes: '. $string->attributes() .'<br />';
}

Didn't work, originally it's for strings but none of them are strings...

foreach ($xml->Formula as $element) {
  foreach($element as $key => $val) {
   echo "{$key}: {$val}";
  }

Didn't work either, I needed something like this to work so I can use the values from the array without knowing what exactly the value will be called..

5
  • Does your XML have a root tag? Or is it just a bunch of formula tags? Commented Aug 27, 2012 at 19:56
  • Are you in a position to not use XML? If you're able to use JSON instead, a simple json_decode($json, TRUE) call would be all that you'd need. Commented Aug 27, 2012 at 19:56
  • attributes are an object, typecast it as an array $attributes = $string->attributes(); $attributes = (array) $attributes; then you can snag whatever you want. Commented Aug 27, 2012 at 19:58
  • The xml is as displayed pretty much, also yes I'm sadly locked into using an XML. $attributes = $string->attributes(); $attributes = (array); echo 'attributes: '. $attributes .'<br />'; Error'd Commented Aug 27, 2012 at 20:02
  • Suggest reading here: php.net/manual/en/class.simplexmliterator.php -- there are several XMl2Array example functions in the comments. Commented Aug 27, 2012 at 21:19

4 Answers 4

20

This is your best bet, and it should eliminate all the SimpleXMLElement objects and instead give you nothing but arrays:

$xml = simplexml_load_file("test.xml");
$xml_array = unserialize(serialize(json_decode(json_encode((array) $xml), 1)));
print_r($xml_array);

Makes the difference between this:


Array with SimpleXMLElement objects


And this:


All arrays - no mixture with SimpleXMLElement objects


Hope that helps... :)

Sign up to request clarification or add additional context in comments.

2 Comments

Works for me in short variant: $xml_array = json_decode(json_encode((array) $firmInfoXml), 1)
even shorter: json_decode(json_encode($xml), 1); (no need to cast)
9

You can't access children by using a foreach on the node itself, you need to use .children():

$s =<<<EOS
<root>
<Formula>
<formulaname>Basic</formulaname>
<movespeed>1</movespeed>
<box>4</box>
<chicken>3</chicken>
<ducks>1</ducks>
<cereal>2</cereal>
</Formula>
</root>
EOS;

$xml = simplexml_load_string($s);

foreach ($xml->Formula as $element) {
    foreach($element->children() as $key => $val) {
        echo "{$key}: {$val}";
    }
}

5 Comments

It didn't echo anything out v.v
@GinzoMilani updated my answer to something that worked for me
teamrequeue.net/DMQuests/upload/users/monckey100/formulas/… That's the xml I'm using as a test, the contents vary from each xml though
@GinzoMilani - can you explain in more detail why this doesn't work for you? As far as I can tell if you put your XML in the above code, it should print out the child elements. +1
@GinzoMilani your XML should have a root node; if you don't have one you can skip the outer loop :)
9

for your example this code is enough:

$xml = simplexml_load_file('formula.xml');
$arr = (array) $xml;
var_dump($arr);

and your xml goes into array
formula.xml contains your xml

1 Comment

works for only 1 level (for deeper trees, @jerdiggity's answer is better)
3

If you have cdata and and attributes in the same node, using the methods above will omit the attributes.

try using this method:

function xml2array($xmlObject, $out = [])
{
    foreach($xmlObject->attributes() as $attr => $val)
        $out['@attributes'][$attr] = (string)$val;

    $has_childs = false;
    foreach($xmlObject as $index => $node)
    {
        $has_childs = true;
        $out[$index][] = xml2array($node);
    }
    if (!$has_childs && $val = (string)$xmlObject)
        $out['@value'] = $val;

    foreach ($out as $key => $vals)
    {
        if (is_array($vals) && count($vals) === 1 && array_key_exists(0, $vals))
            $out[$key] = $vals[0];
    }
    return $out;
}
$xml = simplexml_load_string($xml_string, 'SimpleXMLElement', LIBXML_NOCDATA);
$arr = xml2array($xml);

2 Comments

adds a useless @value key on each node even when not required (eg: when there are no attribute), but +1 for pointing out that attributes are lost on above ways when node contains a value.
+1 It's not useless as you know it is a value and not an attribute. If you would need to parse the resulting array you don't need to check if the node has attributes before interpreting the values as such. This should be the accepted answer as the question is how to convert an xml into an array in php (without loosing data)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.