Posted By

djdykes on 08/08/07


Tagged

php array xml simplexml


Versions (?)

Who likes this?

13 people have marked this snippet as a favorite

crucial
huynguye
aubiematt
iloveitaly
nfreear
low
k23
samkamerer
fadlee
Scr34m
ringo380
Priestd09
tux-world


Convert PHP Array to XML or Simple XML Object if you wish


 / Published in: PHP
 

Was fiddling around at work one day thought this might be useful.

  1. class ArrayToXML
  2. {
  3. /**
  4. * The main function for converting to an XML document.
  5. * Pass in a multi dimensional array and this recrusively loops through and builds up an XML document.
  6. *
  7. * @param array $data
  8. * @param string $rootNodeName - what you want the root node to be - defaultsto data.
  9. * @param SimpleXMLElement $xml - should only be used recursively
  10. * @return string XML
  11. */
  12. public static function toXml($data, $rootNodeName = 'data', $xml=null)
  13. {
  14. // turn off compatibility mode as simple xml throws a wobbly if you don't.
  15. if (ini_get('zend.ze1_compatibility_mode') == 1)
  16. {
  17. ini_set ('zend.ze1_compatibility_mode', 0);
  18. }
  19.  
  20. if ($xml == null)
  21. {
  22. $xml = simplexml_load_string("<?xml version='1.0' encoding='utf-8'?><$rootNodeName />");
  23. }
  24.  
  25. // loop through the data passed in.
  26. foreach($data as $key => $value)
  27. {
  28. // no numeric keys in our xml please!
  29. if (is_numeric($key))
  30. {
  31. // make string key...
  32. $key = "unknownNode_". (string) $key;
  33. }
  34.  
  35. // replace anything not alpha numeric
  36. $key = preg_replace('/[^a-z]/i', '', $key);
  37.  
  38. // if there is another array found recrusively call this function
  39. if (is_array($value))
  40. {
  41. $node = $xml->addChild($key);
  42. // recrusive call.
  43. ArrayToXML::toXml($value, $rootNodeName, $node);
  44. }
  45. else
  46. {
  47. // add single node.
  48. $value = htmlentities($value);
  49. $xml->addChild($key,$value);
  50. }
  51.  
  52. }
  53. // pass back as string. or simple xml object if you want!
  54. return $xml->asXML();
  55. }
  56. }

Report this snippet  

Comments

RSS Icon Subscribe to comments
Posted By: maverickblair on January 22, 2008

how do you implement this? where are you connecting to the database table?

Posted By: visual77 on September 24, 2008

This is not a bad little snippet of code, but it has a few drawbacks.

First, it uses Simple XML, which is easier to use than DOMDocument, but is lacking DOMXpath and requires a bit of conversion before you can use it with the XSLTProcessor.

Second, it only lets you fire it off once before returning an XML tree. Further modification is difficult, and would require running it multiple times and then combining the results.

Third, it only supports arrays. Trying to pass a string, can only work if it is an element of the array. If you passed an array of DOMElements, or a mixed collection, or anything besides multidimensional arrays containing only arrays, strings, nulls, or ints, it'll crash.

Fourth, if the array keys are all numeric, it will attempt to add an invalid node to the tree and crash ungracefully.

Fifth, it has no built in support for an XSL driven website and can only be used loosely in conjuction with PHP's XSLTProcessor to that effect.

For an object that fixes all of these issues, check out the DOMi project at http://domi.sourceforge.net - this object is an improved version of DOMDocument, combined with DOMXpath and XSLTProcessor that is built to allow most PHP data structures to be converted to an XML tree flawlessly, lets you run that function multiple times to build up elaborate XML trees, and is designed with XSLTProcessor in mind, and lets you convert from an array to an XML tree and render through the XSLTProcessor in as few as three lines.

Posted By: visual77 on September 24, 2008

In response to my previous comment - ignore item #4. Rereading the code shows me that I missed the section that replaces numeric keys with a string value. However, it will behave oddly. This code replaces "4" with "unknownNode_4" right before removing all non alpha characters, which converts it to "unknownNode".

Posted By: hradek on October 1, 2008

Hi there, this is an excellent snippet and does the job fantastically when you want to accomplish the simple task of converting an array to XML.

Firstly, make sure you pass the $xml as a reference otherwise the stuff inside the recursive. Here is what I mean:

private function convertArray2xml($dataArray, $rootNodeName = 'dataSet', &$xml = null)

Secondly, you can't check if a variable is null the way you do. Here is how it should look:

if(isnull($xml))
{
        $xml = simplexml_load_string("");
}

Finally, to implement this in your code can be very straight forward. After you connect to your database and get back your result set as an array run it through this function. I took it out of this wrapper class and stuck it into my MySQL DBI.

Posted By: Jpsy on June 4, 2009

Nice piece of code that shortened my way. But visual77 and hradek are both correct with their fixes (var by reference, is_null, wrongly removing non alphas). To sum it up, here is my changed code:

` class ArrayToXML { /** * The main function for converting to an XML document. * Pass in a multi dimensional array and this recrusively loops through and builds up an XML document. * * @param array $data * @param string $rootNodeName - what you want the root node to be - defaultsto data. * @param SimpleXMLElement $xml - should only be used recursively * @return string XML */ public static function toXml($data, $rootNodeName = 'data', &$xml=null) { // turn off compatibility mode as simple xml throws a wobbly if you don't. if (iniget('zend.ze1compatibilitymode') == 1) { iniset ('zend.ze1compatibilitymode', 0); }

    if (is_null($xml))
    {
        $xml = simplexml_load_string("<?xml version='1.0' encoding='utf-8'?><$rootNodeName />");
    }

    // loop through the data passed in.
    foreach($data as $key => $value)
    {
        // no numeric keys in our xml please!
        if (is_numeric($key))
        {
            // make string key...
            $key = "unknownNode_". (string) $key;
        }

        // delete any char not allowed in XML element names
        $key = preg_replace('/[^a-z0-9\-\_\.\:]/i', '', $key);

        // if there is another array found recrusively call this function
        if (is_array($value))
        {
            $node = $xml->addChild($key);
            // recrusive call.
            ArrayToXML::toXml($value, $rootNodeName, $node);
        }
        else 
        {
            // add single node.
                            $value = htmlentities($value);
            $xml->addChild($key,$value);
        }

    }
    // pass back as string. or simple xml object if you want!
    return $xml->asXML();
}

} `

Posted By: Jpsy on June 4, 2009

Sorry for the mess that Markdown produced from my code. I tried, but it does not get any better. Let's try again with manual formatting...

Nice piece of code that shortened my way. But visual77 and hradek are both correct with their fixes (var by reference, is_null, wrongly removing non alphas). To sum it up, here is my changed code:

class ArrayToXML
{
    /**
     * The main function for converting to an XML document.
     * Pass in a multi dimensional array and this recrusively loops through and builds up an XML document.
     *
     * @param array $data
     * @param string $rootNodeName - what you want the root node to be - defaultsto data.
     * @param SimpleXMLElement $xml - should only be used recursively
     * @return string XML
     */
    public static function toXml($data, $rootNodeName = 'data', &$xml=null)
    {
        // turn off compatibility mode as simple xml throws a wobbly if you don't.
        if (ini_get('zend.ze1_compatibility_mode') == 1)
        {
            ini_set ('zend.ze1_compatibility_mode', 0);
        }
        
        if (is_null($xml))
        {
            $xml = simplexml_load_string("");
        }
        
        // loop through the data passed in.
        foreach($data as $key => $value)
        {
            // no numeric keys in our xml please!
            if (is_numeric($key))
            {
                // make string key...
                $key = "unknownNode_". (string) $key;
            }
            
            // delete any char not allowed in XML element names
            $key = preg_replace('/[^a-z0-9\-\_\.\:]/i', '', $key);
            
            // if there is another array found recrusively call this function
            if (is_array($value))
            {
                $node = $xml->addChild($key);
                // recrusive call.
                ArrayToXML::toXml($value, $rootNodeName, $node);
            }
            else 
            {
                // add single node.
                                $value = htmlentities($value);
                $xml->addChild($key,$value);
            }
            
        }
        // pass back as string. or simple xml object if you want!
        return $xml->asXML();
    }
}
Posted By: wwwzealdcom on August 26, 2009

Great class with one exception - it doesn't support a common XML structure such as:



<library>
    <book>
        <authorFirst>Mark</authorFirst>
        <authorLast>Twain</authorLast>
        <title>The Innocents Abroad</title>
    </book>
    <book>
        <authorFirst>Charles</authorFirst>
        <authorLast>Dickens</authorLast>
        <title>Oliver Twist</title>
    </book>
</library>

The way to represent this in array form would be:


$library = array(
    book => array(
        array(
            'authorFirst' => 'Mark'
            'authorLast' => 'Twain'
            'title' => 'The Innocents Abroad'
        ),
        array(
            'authorFirst' => 'Charles'
            'authorLast' => 'Dickens'
            'title' => 'Oliver Twist'
        )
    )
);

However using the current class this would output:


<library>
    <book>
        <unknownNode_0>
            <authorFirst>Mark</authorFirst>
            <authorLast>Twain</authorLast>
            <title>The Innocents Abroad</title>
        </unknownNode_0>
        <unknownNode_1>
            <authorFirst>Charles</authorFirst>
            <authorLast>Dickens</authorLast>
            <title>Oliver Twist</title>
        </unknownNode_1>
    </book>
</library>

... which doesn't make a lot of sense.

SO, the class modified to handle the above situation & a non-associative array in a sensible fashion (including above fixes by visual77 and hradek):


class ArrayToXML
{
    /**
     * The main function for converting to an XML document.
     * Pass in a multi dimensional array and this recrusively loops through and builds up an XML document.
     *
     * @param array $data
     * @param string $rootNodeName - what you want the root node to be - defaultsto data.
     * @param SimpleXMLElement $xml - should only be used recursively
     * @return string XML
     */
    public static function toXml($data, $rootNodeName = 'data', &$xml=null)
    {
        // turn off compatibility mode as simple xml throws a wobbly if you don't.
        if (ini_get('zend.ze1_compatibility_mode') == 1)
        {
            ini_set ('zend.ze1_compatibility_mode', 0);
        }

        if (is_null($xml))
        {
            $xml = simplexml_load_string("");
        }

        // loop through the data passed in.
        foreach($data as $key => $value)
        {
            // if numeric key, assume array of rootNodeName elements
            if (is_numeric($key))
            {
                $key = $rootNodeName;
            }

            // delete any char not allowed in XML element names
            $key = preg_replace('/[^a-z0-9\-\_\.\:]/i', '', $key);

            // if there is another array found recrusively call this function
            if (is_array($value))
            {
                // create a new node unless this is an array of elements
                $node = ArrayToXML::isAssoc($value) ? $xml->addChild($key) : $xml;

                // recrusive call - pass $key as the new rootNodeName
                ArrayToXML::toXml($value, $key, $node);
            }
            else
            {
                // add single node.
                $value = htmlentities($value);
                $xml->addChild($key,$value);
            }

        }
        // pass back as string. or simple xml object if you want!
        return $xml->asXML();
    }

    // determine if a variable is an associative array
    public static function isAssoc( $array ) {
        return (is_array($array) && 0 !== count(array_diff_key($array, array_keys(array_keys($array)))));
    }
}
Posted By: wwwzealdcom on August 26, 2009

Another helpful piece of code to add to this class is the reverse of this function which converts XML (or a SimpleXMLElement object) to an array format which can be converted back using the toXML function:


    public static function toArray( $obj, &$arr = null ){
        if ( isnull( $arr ) ) $arr = array();
        if ( isstring( $obj ) ) $obj = new SimpleXMLElement( $obj );
        $children = $obj->children();
        $executed = false;
        foreach ($children as $elementName => $node){
            if($arr[$elementName]!=null){
                if($arr[$elementName][0]!==null){
                    $i = count($arr[$elementName]);
                    ArrayToXML::toArray($node, $arr[$elementName][$i]);
                }else{
                    $tmp = $arr[$elementName];
                    $arr[$elementName] = array();
                    $arr[$elementName][0] = $tmp;
                    $i = count($arr[$elementName]);
                    ArrayToXML::toArray($node, $arr[$elementName][$i]);
                }
            }else{
                $arr[$elementName] = array();
                ArrayToXML::toArray($node, $arr[$elementName]);
            }
            $executed = true;
        }
        if(!$executed&&$children->getName()==""){
            $arr = (String)$obj;
        }
        return $arr;
    }

Posted By: wwwzealdcom on August 30, 2009

Ok so the above doesn't work with arrays of arrays ... the correct (and hopefully final! :)) toXML with its corresponding toArray is below. Non-associative arrays are labelled as 'anon' as with Perl's XML::Simple.

I've also included a commented-out little snippet at the bottom which you can use if you want formatted XML thats easy to read (SimpleXMLElement::asXML() returns it all on one line).




class ArrayToXML
{
    /**
     * The main function for converting to an XML document.
     * Pass in a multi dimensional array and this recrusively loops through and builds up an XML document.
     *
     * @param array $data
     * @param string $rootNodeName - what you want the root node to be - defaultsto data.
     * @param SimpleXMLElement $xml - should only be used recursively
     * @return string XML
     */
    public static function toXML( $data, $rootNodeName = 'ResultSet', &$xml=null ) {

        // turn off compatibility mode as simple xml throws a wobbly if you don't.
        if ( ini_get('zend.ze1_compatibility_mode') == 1 ) ini_set ( 'zend.ze1_compatibility_mode', 0 );
        if ( is_null( $xml ) ) $xml = simplexml_load_string( "" );

        // loop through the data passed in.
        foreach( $data as $key => $value ) {

            // no numeric keys in our xml please!
            if ( is_numeric( $key ) ) {
                $numeric = 1;
                $key = $rootNodeName;
            }

            // delete any char not allowed in XML element names
            $key = preg_replace('/[^a-z0-9\-\_\.\:]/i', '', $key);

            // if there is another array found recrusively call this function
            if ( is_array( $value ) ) {
                $node = ArrayToXML::is_assoc( $value ) || $numeric ? $xml->addChild( $key ) : $xml;

                // recrusive call.
                if ( $numeric ) $key = 'anon';
                ArrayToXML::toXml( $value, $key, $node );
            } else {

                // add single node.
                $value = htmlentities( $value );
                $xml->addChild( $key, $value );
            }
        }

        // pass back as XML
        return $xml->asXML();

    // if you want the XML to be formatted, use the below instead to return the XML
        //$doc = new DOMDocument('1.0');
        //$doc->preserveWhiteSpace = false;
        //$doc->loadXML( $xml->asXML() );
        //$doc->formatOutput = true;
        //return $doc->saveXML();
    }


    /**
     * Convert an XML document to a multi dimensional array
     * Pass in an XML document (or SimpleXMLElement object) and this recrusively loops through and builds a representative array
     *
     * @param string $xml - XML document - can optionally be a SimpleXMLElement object
     * @return array ARRAY
     */
    public static function toArray( $xml ) {
        if ( is_string( $xml ) ) $xml = new SimpleXMLElement( $xml );
        $children = $xml->children();
        if ( !$children ) return (string) $xml;
        $arr = array();
        foreach ( $children as $key => $node ) {
            $node = ArrayToXML::toArray( $node );

            // support for 'anon' non-associative arrays
            if ( $key == 'anon' ) $key = count( $arr );

            // if the node is already set, put it into an array
            if ( isset( $arr[$key] ) ) {
                if ( !is_array( $arr[$key] ) || $arr[$key][0] == null ) $arr[$key] = array( $arr[$key] );
                $arr[$key][] = $node;
            } else {
                $arr[$key] = $node;
            }
        }
        return $arr;
    }

    // determine if a variable is an associative array
    public static function isAssoc( $array ) {
        return (is_array($array) && 0 !== count(array_diff_key($array, array_keys(array_keys($array)))));
    }
}

Posted By: lukep on September 4, 2009

I'm using wwwzealdcom's version of this class, it's extremely useful. However, on my version of PHP (5.2.8 Win32), it seems I have to use the following line instead of the simplexmlloadstring("") as in the original post to avoid having FALSE returned instead of a SimpleXMLElement:

$xml = simplexml_load_string("");

Posted By: lukep on September 4, 2009

Oops, the line to use is in fact:

$xml = simplexml_load_string("");

(this place needs an edit function)

Posted By: lukep on September 4, 2009

Not a fan of Markdown, I have to say.

$xml = simplexml_load_string("");
Posted By: aubiematt on October 21, 2009

Converted this to a CakePHP helper. Hopefully someone will find this useful.

Save this to 'app/view/helpers/simplexml.php'.

Posted By: aubiematt on October 21, 2009

Converted this to a CakePHP helper. Hopefully someone will find this useful.

Save this to 'app/view/helpers/simplexml.php'.

Posted By: nfreear on August 12, 2010

Hi, Thank you for the snippets!

I'd like to use this code in a project that will be open-source, probably using the GPL version 2. Is this OK please, djdykes and others?

Many thanks,

Nick

Posted By: Pixelmixer on September 24, 2010

I've modified @wwwzealdotcom 's code a bit to accept Arrays that can contain a mixture of Arrays and Objects.

Posted By: Pixelmixer on September 24, 2010

`class ArrayToXML { /** * The main function for converting to an XML document. * Pass in a multi dimensional array and this recrusively loops through and builds up an XML document. * * @param array $data * @param string $rootNodeName - what you want the root node to be - defaultsto data. * @param SimpleXMLElement $xml - should only be used recursively * @return string XML */ public static function toXML( $data, $rootNodeName = 'ResultSet', &$xml=null ) {

    // turn off compatibility mode as simple xml throws a wobbly if you don't.
    if ( ini_get('zend.ze1_compatibility_mode') == 1 ) ini_set ( 'zend.ze1_compatibility_mode', 0 );
    if ( is_null( $xml ) ) $xml = new SimpleXMLElement('');

    // loop through the data passed in.
    foreach( $data as $key => $value ) {

        // no numeric keys in our xml please!
        if ( is_numeric( $key ) ) {
            $numeric = 1;
            $key = $rootNodeName;
        }

        // delete any char not allowed in XML element names
        $key = preg_replace('/[^a-z0-9\-\_\.\:]/i', '', $key);

        if( is_object( $value ) ) {
            $value = get_object_vars( $value );         
        }

        // if there is another array found recrusively call this function
        if ( is_array( $value ) ) {
            $node = ArrayToXML::is_assoc( $value ) || $numeric ? $xml->addChild( $key ) : $xml;

            // recrusive call.
            if ( $numeric ) $key = 'anon';
            ArrayToXML::toXml( $value, $key, $node );
        } else {

            // add single node.
            $value = htmlentities( $value );
            $xml->addChild( $key, $value );
        }
    }

    // pass back as XML
    //return $xml->asXML();

// if you want the XML to be formatted, use the below instead to return the XML
    $doc = new DOMDocument('1.0');
    $doc->preserveWhiteSpace = false;
    $doc->loadXML( $xml->asXML() );
    $doc->formatOutput = true;
    return $doc->saveXML();
}


/**
 * Convert an XML document to a multi dimensional array
 * Pass in an XML document (or SimpleXMLElement object) and this recrusively loops through and builds a representative array
 *
 * @param string $xml - XML document - can optionally be a SimpleXMLElement object
 * @return array ARRAY
 */
public static function toArray( $xml ) {
    if ( is_string( $xml ) ) $xml = new SimpleXMLElement( $xml );
    $children = $xml->children();
    if ( !$children ) return (string) $xml;
    $arr = array();
    foreach ( $children as $key => $node ) {
        $node = ArrayToXML::toArray( $node );

        // support for 'anon' non-associative arrays
        if ( $key == 'anon' ) $key = count( $arr );

        // if the node is already set, put it into an array
        if ( isset( $arr[$key] ) ) {
            if ( !is_array( $arr[$key] ) || $arr[$key][0] == null ) $arr[$key] = array( $arr[$key] );
            $arr[$key][] = $node;
        } else {
            $arr[$key] = $node;
        }
    }
    return $arr;
}

// determine if a variable is an associative array
public static function is_assoc( $array ) {
    return (is_array($array) && 0 !== count(array_diff_key($array, array_keys(array_keys($array)))));
}

}`

Posted By: Pixelmixer on September 24, 2010

`class ArrayToXML { /** * The main function for converting to an XML document. * Pass in a multi dimensional array and this recrusively loops through and builds up an XML document. * * @param array $data * @param string $rootNodeName - what you want the root node to be - defaultsto data. * @param SimpleXMLElement $xml - should only be used recursively * @return string XML */ public static function toXML( $data, $rootNodeName = 'ResultSet', &$xml=null ) {

    // turn off compatibility mode as simple xml throws a wobbly if you don't.
    if ( ini_get('zend.ze1_compatibility_mode') == 1 ) ini_set ( 'zend.ze1_compatibility_mode', 0 );
    if ( is_null( $xml ) ) $xml = new SimpleXMLElement('');

    // loop through the data passed in.
    foreach( $data as $key => $value ) {

        // no numeric keys in our xml please!
        if ( is_numeric( $key ) ) {
            $numeric = 1;
            $key = $rootNodeName;
        }

        // delete any char not allowed in XML element names
        $key = preg_replace('/[^a-z0-9\-\_\.\:]/i', '', $key);

        if( is_object( $value ) ) {
            $value = get_object_vars( $value );         
        }

        // if there is another array found recrusively call this function
        if ( is_array( $value ) ) {
            $node = ArrayToXML::is_assoc( $value ) || $numeric ? $xml->addChild( $key ) : $xml;

            // recrusive call.
            if ( $numeric ) $key = 'anon';
            ArrayToXML::toXml( $value, $key, $node );
        } else {

            // add single node.
            $value = htmlentities( $value );
            $xml->addChild( $key, $value );
        }
    }

    // pass back as XML
    //return $xml->asXML();

// if you want the XML to be formatted, use the below instead to return the XML
    $doc = new DOMDocument('1.0');
    $doc->preserveWhiteSpace = false;
    $doc->loadXML( $xml->asXML() );
    $doc->formatOutput = true;
    return $doc->saveXML();
}


/**
 * Convert an XML document to a multi dimensional array
 * Pass in an XML document (or SimpleXMLElement object) and this recrusively loops through and builds a representative array
 *
 * @param string $xml - XML document - can optionally be a SimpleXMLElement object
 * @return array ARRAY
 */
public static function toArray( $xml ) {
    if ( is_string( $xml ) ) $xml = new SimpleXMLElement( $xml );
    $children = $xml->children();
    if ( !$children ) return (string) $xml;
    $arr = array();
    foreach ( $children as $key => $node ) {
        $node = ArrayToXML::toArray( $node );

        // support for 'anon' non-associative arrays
        if ( $key == 'anon' ) $key = count( $arr );

        // if the node is already set, put it into an array
        if ( isset( $arr[$key] ) ) {
            if ( !is_array( $arr[$key] ) || $arr[$key][0] == null ) $arr[$key] = array( $arr[$key] );
            $arr[$key][] = $node;
        } else {
            $arr[$key] = $node;
        }
    }
    return $arr;
}

// determine if a variable is an associative array
public static function is_assoc( $array ) {
    return (is_array($array) && 0 !== count(array_diff_key($array, array_keys(array_keys($array)))));
}

}`

Posted By: Pixelmixer on September 24, 2010

heh.... Sorry for the spamming...

`

Posted By: nickfellowsgmailcom on November 5, 2010

Some older versions of PHP the compiled in SimpleXML library does not have the "addChild" function

Here's my version that has a fallback method if you are not in a position to upgrade your PHP and need this to work fast.

class ArrayToXML { /** * The main function for converting to an XML document. * Pass in a multi dimensional array and this recrusively loops through and builds up http://snipplr.com/view/3491/convert-php-array-to-xml-or-simple-xml-object-if-you-wish/an XML document. * * @param array $data * @param string $rootNodeName - what you want the root node to be - defaultsto data. * @param SimpleXMLElement $xml - should only be used recursively * @return string XML */ public static function toXML( $data, $rootNodeName = 'ResultSet', &$xml=null ) {

    // turn off compatibility mode as simple xml throws a wobbly if you don't.
    if ( ini_get('zend.ze1_compatibility_mode') == 1 ) ini_set ( 'zend.ze1_compatibility_mode', 0 );
    if ( is_null( $xml ) ) $xml = simplexml_load_string( "" );

    // loop through the data passed in.
    foreach( $data as $key => $value ) {

        // no numeric keys in our xml please!
        if ( is_numeric( $key ) ) {
            $numeric = 1;
            $key = $rootNodeName;
        }

        // delete any char not allowed in XML element names
        $key = preg_replace('/[^a-z0-9\-\_\.\:]/i', '', $key);

        // if there is another array found recursively call this function
        if ( is_array( $value ) ) {

            if ( ArrayToXML::is_assoc( $value ) || $numeric ) {

                // older SimplXMLElement Libraries do not have the addChild Method
                if (method_exists('SimpleXMLElement','addChild'))
                {
                    $node = $xml->addChild( $key );
                }
                else
                {// alternative / dirty method for adding a child
                 $domchild = new DOMElement($key,$value);
                 $dom= new DOMDocument;
                 $dom = dom_import_simplexml($xml);
                 $dom->appendChild($domchild);
                 $xml = simplexml_import_dom($dom);
                 $node = $xml;
                }

            }else{
                $node =$xml;
            }

            // recrusive call.
            if ( $numeric ) $key = 'anon';
            ArrayToXML::toXml( $value, $key, $node );
        } else {

                // older SimplXMLElement Libraries do not have the addChild Method
                if (method_exists('SimpleXMLElement','addChild'))
                {
                    $xml->addChild( $key );
                }
                else
                {   // alternative / dirty method for adding a child
                     $domchild = new DOMElement($key,$value);
                     $dom= new DOMDocument;
                     $dom = dom_import_simplexml($xml);
                     $dom->appendChild($domchild);
                     $xml = simplexml_import_dom($dom);
                }
        }
    }

    // pass back as XML
    return $xml->asXML();

// if you want the XML to be formatted, use the below instead to return the XML
    //$doc = new DOMDocument('1.0');
    //$doc->preserveWhiteSpace = false;
    //$doc->loadXML( $xml->asXML() );
    //$doc->formatOutput = true;
    //return $doc->saveXML();
}


/**
 * Convert an XML document to a multi dimensional array
 * Pass in an XML document (or SimpleXMLElement object) and this recrusively loops through and builds a representative array
 *
 * @param string $xml - XML document - can optionally be a SimpleXMLElement object
 * @return array ARRAY
 */
public static function toArray( $xml ) {
    if ( is_string( $xml ) ) $xml = new SimpleXMLElement( $xml );
    $children = $xml->children();
    if ( !$children ) return (string) $xml;
    $arr = array();
    foreach ( $children as $key => $node ) {
        $node = ArrayToXML::toArray( $node );

        // support for 'anon' non-associative arrays
        if ( $key == 'anon' ) $key = count( $arr );

        // if the node is already set, put it into an array
        if ( isset( $arr[$key] ) ) {
            if ( !is_array( $arr[$key] ) || $arr[$key][0] == null ) $arr[$key] = array( $arr[$key] );
            $arr[$key][] = $node;
        } else {
            $arr[$key] = $node;
        }
    }
    return $arr;
}

// determine if a variable is an associative array
public static function is_assoc( $array ) {
    return (is_array($array) && 0 !== count(array_diff_key($array, array_keys(array_keys($array)))));
}

}

Posted By: OmerHassan on December 3, 2010

Hi,

I just wrote a simple class to convert array to DOMDocument. Here it is: http://code.google.com/p/array-to-domdocument/.

Posted By: seanvillanigmailcom on March 18, 2011

This is a nice little method. I've added some code to automatically ad cdata if it's not a number:

// add single node. $value = htmlentities($value);

            //add cdata if not numeric
            if (!is_numeric($value))
            {
                $dom = dom_import_simplexml($xml);
                $value = $dom->ownerDocument->createCDATASection($value);
                $dom->appendChild($value);
            }

            // add child
            $xml->addChild($key, $value);

You need to login to post a comment.