PDA

View Full Version : SimpleXML Object to Array



dsk3801
05-20-2006, 07: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
05-02-2008, 12:38 AM
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
05-02-2008, 01: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
08-22-2008, 12:02 PM
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
08-22-2008, 01: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
07-19-2009, 12:15 AM
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
08-28-2009, 03: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
09-02-2009, 05: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 ;
}