Search code examples
phpsimplexml

PHP Simplexml iterator


How to elaborate an array reflecting the structure of the following xml ?

Thanks in advance.

XML source :

<document>
  <section type="group" width="100">
        <section type="list" width"50"/>
        <style>classe1 {color:red}</style>
        <section type="text" height="25">azerty</section>
  </section>
</document>

Please note the three tags ('section', 'style' then 'section') embedded in the first level 'section'

Example of desired generated array should reflecting this embedding, attributes and tags order :

Array
{
[0]=>Array
    {
    [key]=>section
    [attributes]=>Array
        {
        [type]=>group
        [width]=>100
        }
    [0]=>Array
        {
        [key]=>section
        [attributes]=>Array
            {
            [type]=>list
            [width]=>50
            }
        }
    [1]=>Array
        {
        [key]=>style
        [content]=>classe1 {color:red}
        }
    [2]=>Array
        {
        [key]=>section
        [attributes]=>Array
            {
            [type]=>text
            [width]=>25
            }
        [content]=>azerty
        }
    }
}

I tried without success whith this code :

<?php 
function xml2array($fName)
    {
    $sxi = new SimpleXmlIterator($fName, null, true);
    return sxiToArray($sxi);
    }

function sxiToArray($sxi)
    {
    $a = array();
    for( $sxi->rewind(); $sxi->valid(); $sxi->next() ) 
        {
        if(!array_key_exists($sxi->key(), $a))
            $a[$sxi->key()] = array();
        if($sxi->hasChildren())
            $a[$sxi->key()][] = sxiToArray($sxi->current());
        else
            {
            $a[$sxi->key() ]['attributs'] = $sxi->attributes();
            $a[$sxi->key()][] = strval($sxi->current());
            }
        }
    return $a;
    }

try
    {
    $catArray = xml2array("temp.xml");
    echo '<pre>'.print_r($catArray,true);
    }
catch(Exception $e)
    {
    echo 'ERREUR : '.$e->getMessage();
    }
?>

Solution

  • I've updated the code to achieve what I think your after. There are a few bits where I've managed the arrays differently. Especially with attributes - I've added them one at a time to allow me to create the key/value setup.

    <?php
    error_reporting(E_ALL);
    ini_set('display_errors', 1);
    
    function xml2array($fName)
    {
        $sxi = new SimpleXmlIterator($fName, null, true);
        $sxi->rewind();
        return sxiToArray($sxi)[0];
    }
    
    function sxiToArray($sxi)
    {
       $a = array();
       for( $sxi->rewind(); $sxi->valid(); $sxi->next() )
        {
            $newData = [];
            $newData['key'] = $sxi->key();
            foreach ( $sxi->current()->attributes() as $key=>$attribute) {
                $newData['attributes'][(string)$key] = (string)$attribute;
            }
            if($sxi->hasChildren())  {
                $newData = array_merge( $newData, sxiToArray($sxi->current()));
            }
            else
            {
                if ( strlen(strval($sxi->current())) > 0 )    {
                    $newData['content'] = strval($sxi->current());
                }
            }
            $a[] = $newData;
        }
        return $a;
    }
    
    try
    {
        $catArray = xml2array("t1.xml");
        echo '<pre>'.print_r($catArray,true);
    }
    catch(Exception $e)
    {
        echo 'ERREUR : '.$e->getMessage();
    }
    {
        echo 'ERREUR : '.$e->getMessage();
    }
    

    I also had to correct the XML as

    <section type="list" width"50"/>
    

    should be

    <section type="list" width="50"/>
    

    (missing =)