0

I need to convert an array of indefinite depth to an xml string. I thought a recursive function would be better to this since the depth of the array is not unknown and is mostly of 3 levels. Here is the recursive function that I have come up so far

function array2xml($data, $key = ''){
    if(!is_array($data)){
        return "<".$key.">".$data."</".$key.">";
    }
    else{
        foreach($data as $key => $value){
            if(!is_array($value)){
                return array2xml($value, $key);
         }
        else{
            return "<".$key.">".array2xml($value)."</".$key.">";
        }
    }
}

This is the inital call but it returns only the first element in the array. For instance,

echo array2xml([
    'students' => [
        'names' => [
            'frank' => '12',
            'jason' => '13',
            'beth' => '14'
        ],
        'groups' => [
            'yellow' => '165',
            'green' => '98'
        ]
    ]
]);

Returns this output

<students><names><frank>12</frank></names></students>

Would appreciate it if someone could fix this recursive function so that the elements in the array are printed like this

<students> 
<names>
    <frankDiaz>12</frank>
    <jasonVaaz>13</jason>
    <bethDoe>14</beth>
</names>
<groups>
    <yellow>165</yellow>
</groups>

3 Answers 3

2

The problem is that you you use return in your function's foreach loop and therefore break out of the loop/function prematurely...

Of course you don't factor in formatting etc. either; but that's a minor point.

Update notes

  • The function no longer uses echo to output the code instead it is returned as a string which can be assigned to a variable or printed itself
  • Added camelCase names as updated in the question

Code

$array = [
    'students' => [
        'names' => [
            'frankDiaz' => '12',
            'jasonVaaz' => '13',
            'bethDoe' => '14'
        ],
        'groups' => [
            'yellow' => '165',
            'green' => '98'
        ]
    ]
];

function array2xml($array, $tabs = 0) {
    $xml = "";
    foreach ($array as $key => $arr) {
        if (is_array($arr)) {
            $xml .= str_repeat("    ", $tabs) . "<$key>\n";
            $xml .= array2xml($arr, $tabs + 1);
            $xml .= str_repeat("    ", $tabs) . "</$key>\n";
        } else {
            $xml .= str_repeat("    ", $tabs) . "<$key>$arr</$key>\n";
        }
    }
    return $xml;
}

echo array2xml($array);

Output:

<students>
    <names>
        <frankDiaz>12</frankDiaz>
        <jasonVaaz>13</jasonVaaz>
        <bethDoe>14</bethDoe>
    </names>
    <groups>
        <yellow>165</yellow>
        <green>98</green>
    </groups>
</students>
Sign up to request clarification or add additional context in comments.

5 Comments

Wow nice. This works but the only issue is I need to assign the xml to a string instead of echoing
Also, I need to maintain the text camelcase. Check my updated example. In your code, it changes the keys to small case
@SaeeshTendulkar I'm unsure what you mean when you say it changes the keys to lower case. This code is very much wysiwyg i.e. if the array has camelCase keys then the output will have camelCase keys. I have added the examples from the updated question. Hopefully I've understood correctly?
@SaeeshTendulkar I have updated the code to return the string rather than echo it. Now you can do either echo array2xml(...) or $xmlString = array2xml(...)
@SaeeshTendulkar you mean if you look at it with dev tools? (e.g. right click and inspect element in chrome?) That's just because your browser is changing the tag name to lower case if you view source instead then you should see it properly?
0

A variation on @Steven's answer above, but creating actual xml with simplexml:

$xml_string = "";
function array2xml($array) {
    global $xml_string;
    foreach ($array as $key => $arr) {        
        if (is_array($arr)) {            
            $xml_string .=  "<$key>\n";
            array2xml($arr);
        }
         else {
            $xml_string .=  "<$key>". $arr;
        }
         $xml_string .=  "</$key>\n";        
    }
}
array2xml($array);
$final = simplexml_load_string($xml_string);
echo $final->asXML();

Comments

-1

the output still works as an XML, just not as easily human readable. To get things on new lines try inputting a carriage return line feed after every element.

1 Comment

What is your answer? A good answer posts how to fix the problem and describes why the answer works.

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.