hakuna matata
hakuna matata

Reputation: 3327

Recursive Expat XML to PHP Array

I wrote a recursive function that is supposed to convert an xml into an associative array. The function I wrote so far worked with the root element containing 1 child only, however when I tried it on an xml which the root has more than 1 child, it only outputted the first child.

Here is the function I wrote: $values is the values array from xml_parse_into_struct.

    function _xml2array($append, $values, $i) {
    if($i == count($values) - 1) {
        return $append;
    }

    switch($values[$i]['type']) {
        case 'open':
            $tag = $values[$i]['tag'];
            $append[$tag][] = _xml2array($append[$tag], $values, ++$i);
            return $append;
        case 'complete':
            $tag = $values[$i]['tag'];
            $val = $values[$i]['value'];
            $append[$tag] = $val;
            return _xml2array($append, $values, ++$i);
        case 'close':
            return $append;
    }
}

function xml2array($values) {
    return _xml2array(array(), $values, 0);
}

And here is the xml I'm working on:

<?xml version="1.0"?>

<espadas>
    <espada>
        <name>Coyote Starrk</name>
        <rank>Primera</rank>
        <resurreccion>
            <release-command>Kick About</release-command>
            <zan-name>Los Lobos</zan-name>
        </resurreccion>
    </espada>
    <espada>
        <name>Baraggan Louisenbairn</name>
        <rank>Segunda</rank>
        <resurreccion>
            <release-command>Rot</release-command>
            <zan-name>Arrogante</zan-name>
        </resurreccion>
    </espada>
</espadas>

And here is the output I'm getting:

Array
(
    [ESPADAS] => Array
        (
            [0] => Array
                (
                    [ESPADA] => Array
                        (
                            [0] => Array
                                (
                                    [NAME] => Coyote Starrk
                                    [RANK] => Primera
                                    [RESURRECCION] => Array
                                        (
                                            [0] => Array
                                                (
                                                    [RELEASE-COMMAND] => Kick About
                                                    [ZAN-NAME] => Los Lobos
                                                )

                                        )

                                )

                        )

                )

        )

)

What am I doing wrong that I'm only getting the first child? Any kind of help would be appreciated.

EDIT: Tried debugging again, and realized I need to put a base case. But that still leaves me with an array with the first child only.

Upvotes: 1

Views: 212

Answers (1)

hakre
hakre

Reputation: 197712

Your code has the expectation encoded that there is one child-element with the same tag-name.

$append[$tag] = _xml2array ...

This is a wrong expectation. XML can have 0-n child-element(s) with the same tag-name.

Therefore you need to encode the case, that there can be zero or more tagnames:

$append[$tag][] = _xml2array ...

As you also do the same mistake on the complete state, you need to modify your code there as well, which I leave as a trivial excercise to apply the given answer there, too.

Upvotes: 1

Related Questions