Page 1 of 1

Convert XML to Array

Posted: Wed Nov 08, 2006 10:18 am
by Ollie Saunders
Does anybody know how to convert XML to an array? (Actually XHTML)
Currently I am recursively casting to array from a simpleXml object but this doesn't appear to work correctly all the time.

Example:

Code: Select all

<div><ul><li class="error">Zim</li><li><ul><li class="error">Foo</li><li class="error">Bar</li></ul></li><li class="note">Gir</li></ul><label for="txt">foo</label><textarea disabled="disabled" id="txt" name="txt" rows="5" cols="20"></textarea></div>
note the 'note' and 'error' classes on the list items

Code: Select all

Array
(
    [div] => Array
        (
            [label] => foo
            [textarea] => Array
                (
                    [@attributes] => Array
                        (
                            [cols] => 20
                            [disabled] => disabled
                            [id] => txt
                            [name] => txt
                            [rows] => 5
                        )

                )

            [ul] => Array
                (
                    [li] => Array
                        (
                            [0] => Zim
                            [1] => Array
                                (
                                    [ul] => Array
                                        (
                                            [li] => Array
                                                (
                                                    [0] => Foo
                                                    [1] => Bar
                                                )

                                        )

                                )

                            [2] => Gir
                        )

                )

        )

)
I'm doing this because I want to test for equality between to pieces of HTML. The HTML is considered equal when they contain the same tags in the same structure with the same attributes with the same values. Critically, neither whitespace between tags nor attribute order should not be considered grounds for inequality.

This is the full code of what I'm doing at the moment:

Code: Select all

protected function assertEqualHtml($actual, $expected)
    {
        $actualXml   = simplexml_load_string('<root>' . $actual   . '</root>');
        $expectedXml = simplexml_load_string('<root>' . $expected . '</root>');
        $actual      = (array)$actualXml;
        $expected    = (array)$expectedXml;
        $this->_ksortRecursive($actual);
        $this->_ksortRecursive($expected);

        if ($actual !== $expected) {
            $this->fail('HTML Equality assertion');
            echo '<br /><b>This...</b>';
            $this->dump($actual);
            echo '<b>should be equal to this...</b>';
            $this->dump($expected);
            return false;
        }
        echo '<br /><b>These are considered equal...</b>';
        $this->dump($actual);
        $this->dump($expected);
        $this->pass();
        return true;
    }
    private function _ksortRecursive(array &$array)
    {
        ksort($array);
        foreach ($array as &$v) {
            if (is_object($v)) { // recursive array cast here 
                $v = (array)$v;
            }
            if (is_array($v)) {
                $this->_ksortRecursive($v);
            }
        }
    }

Posted: Wed Nov 08, 2006 2:18 pm
by brendandonhue
Have you tried xml_parse_into_struct()?

Posted: Wed Nov 08, 2006 5:11 pm
by Ollie Saunders
well trying with

Code: Select all

xml_set_character_data_handler() and xml_set_element_handler()
at the moment. do you think xml_parse_into_struct is going to be easier?

Posted: Wed Nov 08, 2006 6:49 pm
by brendandonhue
If you take a look at the comments on the manual page for parse into struct, you can find some good code to help you along.

Posted: Thu Nov 09, 2006 3:18 am
by Ollie Saunders
brendandonhue wrote:If you take a look at the comments on the manual page for parse into struct, you can find some good code to help you along.
Thanks. Yeah there was actually a complete solution already there. I must have tried about 5 different ones from phpClasses and they all sucked or didn't work.