The first is the xml_to_array function witch will read through an entire xml tree and convert it into a single multi-dimensional array. That is each node in the root node will be added as items in the array and all children and properties will be added to the respective items. This is done in a completely recursive manner so that nodes within nodes within nodes will be fully read and created as arrays within arrays within arrays. The exact format of the generated array is dependent on the options selected.
The default options will merge all the properties and children directly into the node but this may need to be disabled if you have children with the same name as properties or if you need to distinguish between the two types.
Here is a sample XML file, from a svn dump.
svn log --non-interactive --xml <?xml version="1.0"?> <log> <logentry revision="114"> <author>pynej</author> <date>2010-01-11T14:20:42.200771Z</date> <msg>Removed smarty 2.0 code. </msg> </logentry> <logentry revision="113"> <author>pynej</author> <date>2008-08-08T05:14:31.046815Z</date> <msg>* Changed videos to search recursively. This may be configured by an extra variable in the future.</msg> </logentry> </log>
Calling the conversion with the default options would look like so.
print_r(xmlutils::xml_to_array($xml)); Array ( [name] => log [0] => Array ( [name] => logentry [revision] => 114 [author] => pynej [date] => 2010-01-11T14:20:42.200771Z [msg] => Removed smarty 2.0 code. ) [1] => Array ( [name] => logentry [revision] => 113 [author] => pynej [date] => 2008-08-08T05:14:31.046815Z [msg] => * Changed videos to search recursively. This may be configured by an extra variable in the future. ) )
Where as the call with no options generates the more detailed but less user friendly output.
print_r(xmlutils::xml_to_array($xml), 0); Array ( [name] => log [children] => Array ( [0] => Array ( [name] => logentry [attributes] => Array ( [revision] => 114 ) [children] => Array ( [0] => Array ( [name] => author [value] => pynej ) [1] => Array ( [name] => date [value] => 2010-01-11T14:20:42.200771Z ) [2] => Array ( [name] => msg [value] => Removed smarty 2.0 code. ) ) ) [1] => Array ( [name] => logentry [attributes] => Array ( [revision] => 113 ) [children] => Array ( [0] => Array ( [name] => author [value] => pynej ) [1] => Array ( [name] => date [value] => 2008-08-08T05:14:31.046815Z ) [2] => Array ( [name] => msg [value] => * Changed videos to search recursively. This may be configured by an extra variable in the future. ) ) ) ) )
A more useful format might be to retail the attribute/children breakdown but processes the rest.
print_r(xmlutils::xml_to_array($xml), xmlutils::XML_MERGE_ATTRIBUTES | xmlutils::XML_VALUE_PAIRS | xmlutils::XML_MERGE_VALUES); Array ( [name] => log [children] => Array ( [0] => Array ( [name] => logentry [revision] => 114 [children] => Array ( [author] => pynej [date] => 2010-01-11T14:20:42.200771Z [msg] => Removed smarty 2.0 code. ) ) [1] => Array ( [name] => logentry [revision] => 113 [children] => Array ( [author] => pynej [date] => 2008-08-08T05:14:31.046815Z [msg] => * Changed videos to search recursively. This may be configured by an extra variable in the future. ) ) ) )
The second function array_to_xml will to the inverse of this and will generate a XML Tree from a complex anonymous array object. This object can contain any amount of data and will be recursively traversed and added to the tree.
Also note that XML Tree's cant have shared nodes or references so if any exist in the source object the data in them will be duplicated in the XML Tree. There is no way to preserve these references with this tool. Also note that no recursion checks are done so an object with circular recursion will lock up the process.
The following array converted to XML will look like so.
print_r($logList); Array ( [name] => log [0] => Array ( [name] => logentry [revision] => 114 [author] => pynej [date] => 2010-01-11T14:20:42.200771Z [msg] => Removed smarty 2.0 code. ) [1] => Array ( [name] => logentry [revision] => 113 [author] => pynej [date] => 2008-08-08T05:14:31.046815Z [msg] => Array ( [0] => * Added links to the debug section to view the contents of ajax calls. [1] => * Added query->get_md5 to calculate the md5 hash of a query result. ) )
print_r(xmlutils::array_to_xml($logList)); <?xml version="1.0" encoding="utf-8"?> <data> <name>log</name> <data-item> <name>logentry</name> <revision>114</revision> <author>pynej</author> <date>2010-01-11T14:20:42.200771Z</date> <msg>Removed smarty 2.0 code.</msg> </data-item> <data-item> <name>logentry</name> <revision>113</revision> <author>pynej</author> <date>2008-08-08T05:14:31.046815Z</date> <msg> <msg-item>* Added links to the debug section to view the contents of ajax calls.</msg-item> <msg-item>* Added query->get_md5 to calculate the md5 hash of a query result.</msg-item> </msg> </data-item> </data>
Source Code:
xmlutils.php /** * This class contains mothods to convert a xml tree into a complex array with nested properties and to convert a complex array object into an xml tree. * * @package xml-utils * @author Jeremy Pyne <jeremy.pyne@gmail.com> * @license CC:BY/NC/SA http://creativecommons.org/licenses/by-nc-sa/3.0/ * @lastupdate February 16 2010 * @version 1.5 */ final class xmlutils { /** * Add a levels attributes directly to the levels node instead of into an attributes array. * */ const XML_MERGE_ATTRIBUTES = 1; /** * Merge the attribures of a level into the parent level that they belong to. * */ const XML_MERGE_VALUES = 2; /** * Add a levels children directly to the levels node instead of into a children array. * */ const XML_MERGE_CHIILDREN = 4; /** * Process value as a lone entry under their level and ignore the other attributes and children. * */ const XML_VALUE_PAIRS = 8; /** * Split the value of a node into an array on newlines. * */ const XML_SPLIT_VALUES = 16; /** * If a value is an array with a single item, just use the item. * */ const XML_SPLIT_SHIFT = 32; /** * This function will convert an XML tree into a multi-dimentional array. * * @param SimpleXMLElement $xml * @param bitfield $ops * @return array */ public static function xml_to_array($xml, $ops=63) { // Store the name of this level. $level = array(); $level["name"] = $xml->getName(); // Grab the value of this level. $value = trim((string)$xml); // If we have a value, process it. if($value) { // Split the value into an array on newlines. if($ops & self::XML_SPLIT_VALUES) $value = explode("\n", $value); // If the value is an array with one item, remove the array. if($ops & self::XML_SPLIT_SHIFT) if(sizeof($value) == 1) $value = array_shift($value); // Store the value of this level. $level["value"] = $value; } // If this level had a value just return the name/value as an array. if($ops & self::XML_VALUE_PAIRS && array_key_exists("value", $level)) return array($level["name"] => $level["value"]); // Loop through each atribute of this level. foreach($xml->attributes() as $attribute) { // Add each attribure directly to this level in the array. if($ops & self::XML_MERGE_ATTRIBUTES) $level[$attribute->getName()] = (string)$attribute; // Add all the attributes to an attributes array under this level in the array. else $level["attributes"][$attribute->getName()] = (string)$attribute; } // Loop through each child of this level. foreach($xml->children() as $children) { // Get an array of this childs data. $child = self::xml_to_array($children, $ops); if($ops & self::XML_MERGE_VALUES) { // Add each child directly to this level or to the children array of this level in the array. if(sizeof($child) == 1) { // If there is only one child then merge it up. if($ops & self::XML_MERGE_CHIILDREN) $level[array_shift(array_keys($child))] = $child[array_shift(array_keys($child))]; else $level["children"][array_shift(array_keys($child))] = $child[array_shift(array_keys($child))]; } elseif(array_key_exists("value", $child)) { // If there is a value key then merge it up. if($ops & self::XML_MERGE_CHIILDREN) $level[$child["name"]] = $child["value"]; else $level["children"][$child["name"]] = $child["value"]; } elseif(array_key_exists("children", $child)) { // If there are children, then merge them up. if($ops & self::XML_MERGE_CHIILDREN) $level[] = $child; else $level["children"][] = $child; } else { // Otherwise just assigne yourself. if($ops & self::XML_MERGE_CHIILDREN) $level[] = $child; else $level["children"][] = $child; } } else { $level["children"][] = $child; } } return $level; } /** * 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 array_to_xml($data, $rootNodeName = 'data', $xml=null, $parentXml=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 ($rootNodeName == false) { // $xml = simplexml_load_string("<s/>"); //} if ($xml == null) { $xml = simplexml_load_string("<?xml version='1.0' encoding='utf-8'?><$rootNodeName />"); } // loop through the data passed in. foreach($data as $key => $value) { // Create a name for this item based off the attribute name or if this is a item in an array then the parent nodes name. $nodeName = is_numeric($key) ? $rootNodeName . '-item' : $key; $nodeName = preg_replace('/[^a-z1-9_-]/i', '', $nodeName); // If this item is an array then we will be recursine to the logic is more complex. if (is_array($value)) { // If this node is part of an array we have to proccess is specialy. if (is_numeric($key)) { // Another exception if this is teh root node and is an array. In this case we don't have a parent node to use so we must use the current node and not update the reference. if($parentXml == null) { $childXml = $xml->addChild($nodeName); self::array_to_xml($value, $nodeName, $childXml, $xml); // If this is a array node then we want to add the item under the parent node instead of out current node. Also we have to update $xml to reflect the change. } else { $xml = $parentXml->addChild($nodeName); self::array_to_xml($value, $nodeName, $xml, $parentXml); } } else { // For a normal attribute node just add it to the parent node. $childXml = $xml->addChild($nodeName); self::array_to_xml($value, $nodeName, $childXml, $xml); } // If not then it is a simple value and can be directly appended to the XML tree. } else { $value = htmlentities($value); $xml->addChild($nodeName, $value); } } // Pass back as string or simple xml object. return $xml->asXML(); }
33 comments:
I need something like this for quite some time.
Cheers, Jeremy Cushing
Sorry,
but it seems like the posted source code results uncompleted.
If I run, first I get:
Parse error: syntax error, unexpected ';', expecting T_FUNCTION in C:\Program Files\o2app\efleet\htdocs\xmlutils.php on line 190
Then (if I add the final brace before php end tag) I get:
Fatal error: Call to a member function getName() on a non-object in C:\Program Files\o2app\efleet\htdocs\xmlutils.php on line 54
I think something in the code displayed is missing...
Can you help me please ?
Yes its just the closing { that was missing. As for the error your seeing i guess it doesn't have the best error checking. I'm not sure how you were calling the xml_to_array method but you nee to pass in a SimpleXMLElement object for it to convert. the getName method that is called is a method on this SimpleXMLElement object.
You're right.
I solved.
Thanks!
this is working properly but when i am sending the child node as
transaction_10 its getting transaction_1
transaction_20 its getting transaction_2
transaction_30 its getting transaction_3
-----------------------------------
this is working properly but when i am sending the child node as
transaction_10 its getting transaction_1
transaction_20 its getting transaction_2
transaction_30 its getting transaction_3
Hrm, I haven't seen that problem before. If you want to send be a sample file/sample code that demonstrates this problem and I can take a look.
Thanks alot i fixed that issues
I'm trying to be able to go back and forth between an array and XML multiple times. But as I try your different examples, the data keeps changing and I can never return the data to it's original form. I copied your example xml into example.xml. I put your code in xmlutils.php and fixed the } issue. Here's my example php:
include('xmlutils.php');
$xmlStr = file_get_contents('example.xml');
$xmlObj = simplexml_load_string($xmlStr);
//$newarray=xmlutils::xml_to_array($xmlObj, xmlutils::XML_MERGE_ATTRIBUTES | xmlutils::XML_VALUE_PAIRS | xmlutils::XML_MERGE_VALUES);
$newarray=xmlutils::xml_to_array($xmlObj, 0);
$xmlStr2=xmlutils::array_to_xml($newarray);
$xmlObj2= simplexml_load_string($xmlStr2);
//$newarray2=xmlutils::xml_to_array($xmlObj2, xmlutils::XML_MERGE_ATTRIBUTES | xmlutils::XML_VALUE_PAIRS | xmlutils::XML_MERGE_VALUES);
$newarray2=xmlutils::xml_to_array($xmlObj2, 0);
print_r($newarray);
echo "\n\n again \n\n";
print_r($newarray2);
Ethan I didn't write these methods to me cyclical like you are trying to sue them. I actually had them in two different places and combined them here for their functionality. To do what you want will require some rewriting of the logic of the decoding? logic to more closely replicate the original object.
Thank you for your response. I did like the functionality you provided with these and find it's one of the better examples I found in my searches. I did find another example that fit my needs from another programmer. But to make it work, he formatted the array in a specialized way. So while it won't work for just any multidimensional array as yours does, it does fit my needs for now. Thank you, Ethan.
This is a small library to Convert XML to Array and Array to XML in PHP.this type of functionality is required for interacting other language application by using xml as a common interface used by both applications
digital signature sharepoint
Hi, I have a sitemap. php and rss in training I need sitemap.XML, how they manage to make it pass? office@galati-anunturi.ro
is it possible if I have an xml that looks as below:
pynej
2010-01-11T14:20:42.200771Z
Removed smarty 2.0 code.
pynej
2008-08-08T05:14:31.046815Z
* Changed videos to search recursively. This may be configured by an extra variable in the future.
i get an array that looks as below:
Array
(
[name] => log
[0] => Array
(
[name] => logentry
[revision] => 114
[author] => pynej
[date] => 2010-01-11T14:20:42.200771Z
[date-format] => nl
[msg] => Removed smarty 2.0 code.
)
[1] => Array
(
[name] => logentry
[revision] => 113
[author] => pynej
[date] => 2008-08-08T05:14:31.046815Z
[date-format] => nl
[msg] => * Changed videos to search recursively. This may be configured by an extra variable in the future.
)
)
I can not post xml pity. the point is that if I have a format = "nl" in the date ellement i want to get it out is shown in the array. is that possible? I would greatly facilitated!
In the attributes proccesing section you could ass a bit of code/option to move the attributes to a sibbling node of the current element.
// Loop through each atribute of this level.
foreach($xml->attributes() as $attribute) {
if($attribute->getName() == "format")
$parentLevel[$parent->getName() ' . "_" . $attribute->getName()] = (string)$attribute;
...
}
I have seen that all will say the same thing repeatedly. But in your blog, I had a chance to get some useful and unique information. I would like to suggest your blog in my dude circle. please keep on updates. Hope it might be much useful for us. keep on updating.
PHP Training in Chennai
People have to grab lot of skills and knowledge about big data, analytics. sexiest job of the century. high paying jobs.
online aptitude training
learn core java online
MBA in marketing management
MBA in event management
Big data analytics training
annamalai university distance education mba
Big data for beginners
Analytics courses
Thanks for sharing this useful information.it provides insightful information.Worth reading.
Selenium Training in chennai | Selenium Training in annanagar | Selenium Training in omr | Selenium Training in porur | Selenium Training in tambaram | Selenium Training in velachery
This is excellent information. It is amazing and wonderful to visit your site.Thanks for sharing this information,this is useful to me.
Teradata Online Training
Teradata Classes Online
Teradata Training Online
Online Teradata Course
Teradata Course Online
Wow it is really wonderful and awesome thus it is very much useful for me to understand many concepts and helped me a lot.
Cloud Computing Online Training
Cloud Computing Classes Online
Cloud Computing Training Online
Online Cloud Computing Course
Cloud Computing Course Online
After reading your article I was amazed. I know that you explain it very well. And I hope that other readers will also experience how I feel after reading your article.
Machine Learning certification Online Training in bangalore
Machine Learning certification courses in bangalore
Machine Learning certification classes in bangalore
Machine Learning certification Online Training institute in bangalore
Machine Learning certification course syllabus
best Machine Learning certification Online Training
Machine Learning certification Online Training centers
Inspiring writings and I greatly admired what you have to say , I hope you continue to provide new ideas for us all and greetings success always for you..
web designing training in chennai
web designing training in omr
digital marketing training in chennai
digital marketing training in omr
rpa training in chennai
rpa training in omr
tally training in chennai
tally training in omr
This post is really a fastidious one it assists new web people, who are wishing for blogging.
angular js training in chennai
angular js training in tambaram
full stack training in chennai
full stack training in tambaram
php training in chennai
php training in tambaram
photoshop training in chennai
photoshop training in tambaram
This is the exact information I am been searching for, Thanks for sharing the required infos with the clear update and required points.
sap training in chennai
sap training in velachery
azure training in chennai
azure training in velachery
cyber security course in chennai
cyber security course in velachery
ethical hacking course in chennai
ethical hacking course in velachery
excellent article....keep sharing..
Excellent material with unique content, and it is really important to be aware of blog-based material.
1000 Social BookMarking Sites List
https://ravivarma.in/
Thanks for Sharing
Best Interior Designers
I'm grateful to you for sharing this plenty of valuable assessment. I found this asset most extreme helpful for me. much thanks to you a lot for better do whatever it takes. Edius Video Editing Software
I could following to appreciation for the undertakings you have made recorded as a printed copy this leaflet. I'm trusting the thesame fine take diversion doings from you inside the thinking of as capably. thankful to you...
Bitdefender Antivirus Plus 2019 Crack
Each and every year, when 14th August arrives, it fills our hearts with love for our nation and memories of all those who lost their lives to get freedom for ..Independence Day Of Pakistan Greetings
This blog is great and has a lot of useful information.
mIRC
Post a Comment