Saeesh Tendulkar
Saeesh Tendulkar

Reputation: 703

PHP recursive function to convert multidimensional array to xml

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>

Upvotes: 0

Views: 264

Answers (3)

Steven
Steven

Reputation: 6148

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>

Upvotes: 2

Jack Fleeting
Jack Fleeting

Reputation: 24930

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();

Upvotes: 0

Slingblade
Slingblade

Reputation: 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.

Upvotes: -1

Related Questions