XML to associative array using PHP

Can someone help with converting data from an XML document to an associative array? I run into problems considering that the XML structure is a kind of 3D, and the array is larger than the 2D structure (please forgive my lack of proper terminology). The XML elements have attributes, children and grandchildren (but I never know their names), so I decided that I would try to make the key in the array a concatenation of each child / attribute name and value equal to, Value. The problem is that I need the attribute name and value as part of the key of the concatenated array to make it unique ...

For example:

<Computer id="1"> <OS> <Name>Linux</Name> <Age>Older than me</Age> </OS> </Computer> <Computer id="2"> <OS> <Name>Windows</Name> <Age>Not so much</Age> </OS> </Computer> 

Ideally, you should give:

 [Computer-id-1-OS-Name] = 'Linux' [Computer-id-1-OS-Age] = 'Older than me' [Computer-id-2-OS-Name] = 'Windows' [Computer-id-2-OS-Age] = 'Not so much' 

But I get this result:

 [Computer-id] = '1' [Computer-OS-Name] = 'Linux' [Computer-OS-Age] = 'Older than me' [Computer-id] = '2' [Computer-OS-Name] = 'Windows' [Computer-OS-Age] = 'Not so much' 

So the [Computer-id] key is not unique. I use a recursive function to read values, but I can’t figure out how to get the attribute name and attribute value in the name of subordinate keys ... (By the way, there is a good reason for this, it would seem an illogical task!) Any help would be greatly appreciated .. .

Here is a function that β€œsmoothes” XML data after it has been read in a multidimensional array. I'm not sure I'm going to do it right!

 function flattenArray ($array, $baseName = NULL) { reset($array); while (list ($key, $value) = each($array)) { $outKey = $key . "-"; if (is_array($value)) { flattenArray($value, $baseName . $outKey); } else { $finalKey = $baseName . rtrim($outKey, '-'); $finalValue = $value; echo "$finalKey = $finalValue\n"; } } } 
+7
source share
5 answers

One example would be:

 $dom = new DOMDocument; $dom->loadXML( '<root> <Computer id="1"> <OS> <Name>Linux</Name> <Age>Older than me</Age> </OS> </Computer> <Computer id="2"> <OS> <Name>Windows</Name> <Age>Not so much</Age> </OS> </Computer> </root>' ); $xpath = new DOMXPath($dom); $result = array(); foreach ($xpath->query('//*[count(*) = 0]') as $node) { $path = array(); $val = $node->nodeValue; do { if ($node->hasAttributes()) { foreach ($node->attributes as $attribute) { $path[] = sprintf('%s[%s]', $attribute->nodeName, $attribute->nodeValue); } } $path[] = $node->nodeName; } while ($node = $node->parentNode); $result[implode('/', array_reverse($path))] = $val; } print_r($result); 

Output:

 Array ( [#document/root/Computer/id[1]/OS/Name] => Linux [#document/root/Computer/id[1]/OS/Age] => Older than me [#document/root/Computer/id[2]/OS/Name] => Windows [#document/root/Computer/id[2]/OS/Age] => Not so much ) 

This is not what you are looking for, but it is the beginning and it can be easily customized to give different results.

+5
source

It worked great for me, and it was easy.

 $ob = simplexml_load_file('test.xml'); $json = json_encode($ob); $array = json_decode($json, true); 
+38
source

Read the xml into the DOM object, skip it, save the results in an array. It's simple.

+2
source

here is my function to create a linked array derived from

Recursive listing from SimpleXMLObject to array

 function xml2assoc($obj, &$arr) { $children = $obj->children(); foreach ( $children as $elementName => $node ) { if (!isset($arr[$elementName])) { $arr[$elementName] = array(); } $temp = array(); $attributes = $node->attributes(); foreach ( $attributes as $attributeName => $attributeValue ) { $attribName = strtolower(trim((string) $attributeName)); $attribVal = trim((string) $attributeValue); $temp[$attribName] = $attribVal; } $text = (string) $node; $text = trim($text); if (strlen($text) > 0) { $temp ['text='] = $text; } $arr[$elementName][] = $temp; $nextIdx = count($arr[$elementName]); xml2assoc($node, $arr[$elementName][$nextIdx - 1]); } return; } $xml = '<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType><![CDATA[news]]></MsgType> <ArticleCount>2</ArticleCount> <Articles> <item> <Title><![CDATA[title1]]></Title> <Description><![CDATA[description1]]></Description> <PicUrl><![CDATA[picurl]]></PicUrl> <Url><![CDATA[url]]></Url> </item> <item> <Title><![CDATA[title]]></Title> <Description><![CDATA[description]]></Description> <PicUrl><![CDATA[picurl]]></PicUrl> <Url><![CDATA[url]]></Url> </item> </Articles> </xml> '; $dom = new SimpleXMLElement($xml); $arr = array(); xml2assoc($dom, $arr); print_r($arr); 

generated array:

 Array ( [ToUserName] => Array ( [0] => Array ( [text=] => toUser ) ) [FromUserName] => Array ( [0] => Array ( [text=] => fromUser ) ) [CreateTime] => Array ( [0] => Array ( [text=] => 12345678 ) ) [MsgType] => Array ( [0] => Array ( [text=] => news ) ) [ArticleCount] => Array ( [0] => Array ( [text=] => 2 ) ) [Articles] => Array ( [0] => Array ( [item] => Array ( [0] => Array ( [Title] => Array ( [0] => Array ( [text=] => title1 ) ) [Description] => Array ( [0] => Array ( [text=] => description1 ) ) [PicUrl] => Array ( [0] => Array ( [text=] => picurl ) ) [Url] => Array ( [0] => Array ( [text=] => url ) ) ) [1] => Array ( [Title] => Array ( [0] => Array ( [text=] => title ) ) [Description] => Array ( [0] => Array ( [text=] => description ) ) [PicUrl] => Array ( [0] => Array ( [text=] => picurl ) ) [Url] => Array ( [0] => Array ( [text=] => url ) ) ) ) ) ) ) 
+1
source

Simple arrays can be 2d, but multidimensional arrays can very easily copy a hierarchical structure such as xml.

"Google php associative multidimensional array" for more information.

However, as already mentioned, PHP has a built-in xml parser, so there should be no need to recreate xml inside the array, not to mention smoothing it to a simple array.

In PHP, the structure of your array should look something like this:

 $computers["computers"]["computer-1"]["OS"]["Name"] = "Linux"; $computers["computers"]["computer-1"]["OS"]["Age"] = "Older Than Me"; $computers["computers"]["computer-2"]["OS"]["Name"] = "Windows"; $computers["computers"]["computer-2"]["OS"]["Age"] = "Not so much"; 

etc...

0
source

All Articles