raymak Posted June 8, 2014 Share Posted June 8, 2014 Hello, I am working on creating an XML document. I am trying to accomplish following format, but the code I wrote is giving me different result. I need some help on which type of loop I can use, so I can store all the Env in one element as a attribute. Output I am trying to accomplish this: <Applications> <App AppName="NotePad++"> <Env Prod="server1,server2" DEV="devserver1,devserver2" /> </App> <App AppName="7Zip"> <Env Prod="server3,server4" DEV="devserver3,devserver4" /> </App> </Applications> But, I am getting this: <?xml version="1.0" ?> <Applications> <App AppName="NotePad++"> <Env Prod="server1" /> </App> <App AppName="NotePad++"> <Env Prod="server2" /> </App> <App AppName="NotePad++"> <Env DEV="devserver1" /> </App> <App AppName="NotePad++"> <Env DEV="devserver2" /> </App> <App AppName="7Zip"> <Env Prod="server3" /> </App> <App AppName="7Zip"> <Env Prod="server4" /> </App> <App AppName="7Zip"> <Env DEV="devserver3" /> </App> <App AppName="7Zip"> <Env DEV="devserver4" /> </App> </Applications> Here is the code I wrote: Foreach ($application as $app) { Foreach ($serverlist as $serverenv) { if ($serverenv['appid'] == $app['id']) { $appchild = $doc->createElement( "App" ); $appattr = $main->appendChild($appchild); $appattr->setAttribute("AppName", $app['appname']); $envchild = $doc->createElement("Env"); $envattr = $appchild->appendChild($envchild); $envattr->setAttribute($serverenv['Environment'], $serverenv['servername']); } } } echo $doc->saveXML(); Quote Link to comment Share on other sites More sharing options...
mac_gyver Posted June 8, 2014 Share Posted June 8, 2014 1) when creating an xml document, i find it easier (and clearer) to just use php to create the elements you want. using an xml library isn't necessary unless you are modifying an existing xml document. 2) your loops and logic don't make sense. each pass through the loop is creating/appending new elements. you would either need to detect changes in the related data and/or run loops to reference the related data. 3) providing us with a sample of your input data that you expect to produce the shown output, in a format that we can copy/paste (see var_export()) and use in php code, would help as it would both show the structure and relationship between your arrays of data and allow someone to experiment. Quote Link to comment Share on other sites More sharing options...
Solution mac_gyver Posted June 8, 2014 Solution Share Posted June 8, 2014 i reverse engineered your data from the posted information. here's one way of producing the output, using the php only approach - $application[] = array('id'=>1,'appname'=>'NotePad++'); $application[] = array('id'=>2,'appname'=>'7Zip'); // these could potentially be in any order. allow for arbitrary environments $serverlist[] = array('appid'=>1,'Environment'=>'Prod', 'servername'=>'server1'); $serverlist[] = array('appid'=>1,'Environment'=>'Prod', 'servername'=>'server2'); $serverlist[] = array('appid'=>1,'Environment'=>'DEV', 'servername'=>'devserver1'); $serverlist[] = array('appid'=>1,'Environment'=>'DEV', 'servername'=>'devserver2'); $serverlist[] = array('appid'=>2,'Environment'=>'Prod', 'servername'=>'server3'); $serverlist[] = array('appid'=>2,'Environment'=>'Prod', 'servername'=>'server4'); $serverlist[] = array('appid'=>2,'Environment'=>'DEV', 'servername'=>'devserver3'); $serverlist[] = array('appid'=>2,'Environment'=>'DEV', 'servername'=>'devserver4'); // pre-process server list into appid/environments $data = array(); foreach($serverlist as $s){ if(!isset($data[$s['appid']])){ $data[$s['appid']] = array(); } if(!isset($data[$s['appid']][$s['Environment']])){ $data[$s['appid']][$s['Environment']] = array(); } $data[$s['appid']][$s['Environment']][] = $s['servername']; } //echo '<pre>',print_r($data,true); // examine resulting data header ("Content-Type:text/xml"); echo '<?xml version="1.0" ?>'; echo '<Applications>'; foreach($application as $app){ echo "<App AppName='{$app['appname']}'>"; echo "<Env "; foreach($data[$app['id']] as $env_name=>$servers){ echo "$env_name='".implode(',',$servers)."' "; } echo "/>"; echo "</App>"; } echo '</Applications>'; Quote Link to comment Share on other sites More sharing options...
mac_gyver Posted June 8, 2014 Share Posted June 8, 2014 and once you have the program logic/data, producing the output using an xml library would look like this - // starting with the above code, replace everything from the header() down with this - header ("Content-Type:text/xml"); $sxe = new SimpleXMLElement('<Applications></Applications>'); foreach($application as $app){ $e_appl = $sxe->addChild('App'); $e_appl->addAttribute('AppName', $app['appname']); $e_env = $e_appl->addChild('Env'); foreach($data[$app['id']] as $env_name=>$servers){ $e_env->addAttribute($env_name,implode(',',$servers)); } } echo $sxe->asXML(); Quote Link to comment Share on other sites More sharing options...
raymak Posted June 9, 2014 Author Share Posted June 9, 2014 (edited) Mac_gyver, Thank so much for your time and knowledge for above suggestions. My code looks same as your reversed engineered code. And I apologize for not posting the actual code in time, and it would have saved you a lot of time. I am posting my code anyways, and I will review your suggestions and get back to you. <?php $application = array(); $application[0] = array( "id" => 1, "appname" => "NotePad++" ); $application[1] = array( "id" => 2, "appname" => "7Zip" ); $application[2] = array( "id" => 3, "appname" => "MS Office 2010++" ); $application[3] = array( "id" => 4, "appname" => "Norton Anti Virus" ); $application[4] = array( "id" => 5, "appname" => "Chrome" ); $application[5] = array( "id" => 6, "appname" => "Adobe Reader" ); $serverlist = array(); $serverlist[0] = array( "appid" => 1, "Environment" => "Prod", "servername" => "server1" ); $serverlist[1] = array( "appid" => 1, "Environment" => "Prod", "servername" => "server2" ); $serverlist[2] = array( "appid" => 1, "Environment" => "DEV", "servername" => "devserver1" ); $serverlist[3] = array( "appid" => 1, "Environment" => "DEV", "servername" => "devserver2" ); $serverlist[4] = array( "appid" => 2, "Environment" => "Prod", "servername" => "server3" ); $serverlist[5] = array( "appid" => 2, "Environment" => "Prod", "servername" => "server4" ); $serverlist[6] = array( "appid" => 2, "Environment" => "DEV", "servername" => "devserver3" ); $serverlist[7] = array( "appid" => 2, "Environment" => "DEV", "servername" => "devserver4" ); $data = array(); $doc = new DOMDocument("1.0"); $doc->formatOutput = true; $main = $doc->createElement("Applications"); $doc->appendChild( $main); Foreach ($application as $app) { Foreach ($serverlist as $serverenv) { if ($serverenv['appid'] == $app['id']) { $appchild = $doc->createElement( "App" ); $appattr = $main->appendChild($appchild); $appattr->setAttribute("AppName", $app['appname']); $envchild = $doc->createElement("Env"); $envattr = $appchild->appendChild($envchild); $envattr->setAttribute($serverenv['Environment'], $serverenv['servername']); } } } echo $doc->saveXML(); ?> Edited June 9, 2014 by raymak Quote Link to comment Share on other sites More sharing options...
raymak Posted June 9, 2014 Author Share Posted June 9, 2014 Mac_gyver, Thank you very much for your help. From your code, I learned a new concept of storing values in multiple array inside one variable. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.