Jump to content

Recommended Posts

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();
Link to comment
https://forums.phpfreaks.com/topic/289064-help-with-xml-in-php/
Share on other sites

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.

  • Solution

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>';

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();

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.  :happy-04:

<?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 by raymak
This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.