PDA

View Full Version : SimpleXML Object to Array



dsk3801
May 20th, 2006, 06:13 AM
I work with a lot of XML and have found SimpleXML to be a great tool, but often it's easier to have it all in an array form that still maintains the order of elements. I came up with this function -- maybe someone else will find it useful, too.




function convertXmlObjToArr($obj, &$arr)
{
$children = $obj->children();
foreach ($children as $elementName => $node)
{
$nextIdx = count($arr);
$arr[$nextIdx] = array();
$arr[$nextIdx]['@name'] = strtolower((string)$elementName);
$arr[$nextIdx]['@attributes'] = array();
$attributes = $node->attributes();
foreach ($attributes as $attributeName => $attributeValue)
{
$attribName = strtolower(trim((string)$attributeName));
$attribVal = trim((string)$attributeValue);
$arr[$nextIdx]['@attributes'][$attribName] = $attribVal;
}
$text = (string)$node;
$text = trim($text);
if (strlen($text) > 0)
{
$arr[$nextIdx]['@text'] = $text;
}
$arr[$nextIdx]['@children'] = array();
convertXmlObjToArr($node, $arr[$nextIdx]['@children']);
}
return;
}



If you have the following XML:



<books>
<novel author="John Doe"><title>John's Novel</title></novel>
</books>


You'll get an array similar to:



Array
(
@name => books
@attributes => array ( )
@children => array
(
array
(
@name => novel
@attributes => array ( author => John Doe )
@children => array
(
array ( @name => title, @attributes => array ( ), @text => John's Novel )
)
)
)
)

jamessdeveloper
May 1st, 2008, 11:38 PM
Hi, can you demonstrate further example, e.g.

a) how do you call the function, do you add arguments to the function?
b) what coding syntax do you use to retrieve the array information.

Thanks ~ James

dsk3801
May 2nd, 2008, 12:09 AM
OK... say I have XML like this stored in a file called "books.xml":



<books>
<novel author="John Doe"><title>John's Novel</title></novel>
<novel author="Jane Doe"><title>Jane's Novel</title></novel>
<novel author="Jack Doe"><title>Jack's Novel</title></novel>
</books>


In my PHP code:



$xmlObject = simplexml_load_file('books.xml');
$xmlArr = array();
convertXmlObjToArr($xmlObject, $xmlArr);

foreach ($xmlArr as $arr)
{
// outer array is always base element, in this case, books... we need the children
if (isset($arr['@children']) && is_array($arr['@children']))
{
foreach ($arr['@children'] as $novel)
{
// the title is actually a child element of novel
echo 'Title: ' . $novel['@children'][0]['@text'] . '<br />';

// author is an attribute of the novel tag
echo 'Author: ' . $novel['@attributes']['author'] . '<br /><br />';
}
}
}


I hope this helps.

ad34
Aug 22nd, 2008, 11:02 AM
Hi There !

I also have a problem with simpleXML , I have to make text of an XML file editable, so I parse XML file with attributes() and children() method to build an HTML form.

the problem is to get data back to xml to regenerate xml file

i have the data in an array with post method



[obj] => Array
(
[content] => Array
(
[@attributes] => Array
(

[center_title] => test
)

)

...


it is exactly the same that simpleXML object excepts it s an array and not an object

dont know actually how i gonna get the job done

any ideas ?

dsk3801
Aug 22nd, 2008, 12:55 PM
Honestly, I only use this to quickly read in complex XML files (like RSS/ATOM feeds). If I need to manipulate XML and write it back out to the browser or a file, then I will typically use DOM or XMLWriter. You should check them out in the PHP manual as they'll probably suit your needs better.

Frederic_2008
Jul 18th, 2009, 11:15 PM
Here is my code!
It does not respect attributes but it transformes the Xml to a simpler array. Let me know if you use it or if you find some bugs :-) :thumbsup:


function convertXmlObjToArr($obj, &$arr){
$children = $obj->children();
$executed = false;
foreach ($children as $elementName => $node){
if($arr[$elementName]!=null){
if($arr[$elementName][0]!==null){
$i = count($arr[$elementName]);
convertXmlObjToArr($node, $arr[$elementName][$i]);
}else{
$tmp = $arr[$elementName];
$arr[$elementName] = array();
$arr[$elementName][0] = $tmp;
$i = count($arr[$elementName]);
convertXmlObjToArr($node, $arr[$elementName][$i]);
}
}else{
$arr[$elementName] = array();
convertXmlObjToArr($node, $arr[$elementName]);
}
$executed = true;
}
if(!$executed&&$children->getName()==""){
$arr = (String)$obj;
}
return;
}

matteo
Aug 28th, 2009, 02:16 PM
The same Frederic_2008 code snippet, but without the warning on


if($arr[$elementName]!=null){

in case the


$arr[$elementName] is = NULL

PS: thanks Frederic_2008!



/**
* Parse a SimpleXMLElement object recursively into an Array.
* Attention: attributes skipped
*
*
* @param $xml The SimpleXMLElement object
* @param $arr Target array where the values will be stored
* @return NULL
*/
private function convertXmlObjToArr( $obj, &$arr )
{
$children = $obj->children();
$executed = false;
foreach ($children as $elementName => $node)
{
if( array_key_exists( $elementName , $arr ) )
{
if(array_key_exists( 0 ,$arr[$elementName] ) )
{
$i = count($arr[$elementName]);
$this->convertXmlObjToArr ($node, $arr[$elementName][$i]);
}
else
{
$tmp = $arr[$elementName];
$arr[$elementName] = array();
$arr[$elementName][0] = $tmp;
$i = count($arr[$elementName]);
$this->convertXmlObjToArr($node, $arr[$elementName][$i]);
}
}
else
{
$arr[$elementName] = array();
$this->convertXmlObjToArr($node, $arr[$elementName]);
}
$executed = true;
}
if(!$executed&&$children->getName()=="")
{
$arr = (String)$obj;
}

return ;
}

matteo
Sep 2nd, 2009, 04:12 PM
It was so buggy I had to find for another ready-made solution:
This is perfect:
http://us3.php.net/manual/en/class.simplexmliterator.php#92323


The same Frederic_2008 code snippet, but without the warning on


if($arr[$elementName]!=null){

in case the


$arr[$elementName] is = NULL

PS: thanks Frederic_2008!



/**
* Parse a SimpleXMLElement object recursively into an Array.
* Attention: attributes skipped
*
*
* @param $xml The SimpleXMLElement object
* @param $arr Target array where the values will be stored
* @return NULL
*/
private function convertXmlObjToArr( $obj, &$arr )
{
$children = $obj->children();
$executed = false;
foreach ($children as $elementName => $node)
{
if( array_key_exists( $elementName , $arr ) )
{
if(array_key_exists( 0 ,$arr[$elementName] ) )
{
$i = count($arr[$elementName]);
$this->convertXmlObjToArr ($node, $arr[$elementName][$i]);
}
else
{
$tmp = $arr[$elementName];
$arr[$elementName] = array();
$arr[$elementName][0] = $tmp;
$i = count($arr[$elementName]);
$this->convertXmlObjToArr($node, $arr[$elementName][$i]);
}
}
else
{
$arr[$elementName] = array();
$this->convertXmlObjToArr($node, $arr[$elementName]);
}
$executed = true;
}
if(!$executed&&$children->getName()=="")
{
$arr = (String)$obj;
}

return ;
}