0

I wana to assign a variable such as 'heloo' to an address such as ->system_settings->settings->hostname and i write a function for.now when i write that address manually this function work correctly and assign 'hello' to that address,but,when i wana to gave address dynamically it doesn't work. my function :

<?php
write_xml("->system_settings->settings->hostname",'Helloooooooo');
function write_xml($tag_address,$value) {

    $xml = simplexml_load_file("test.xml")
                 or die("Error: Cannot create object");
    //  $xml->system_settings->settings->hostname = $value;
    $xml->$tag_address=$value;
    $xml->asXML("test.xml");

}
?>

when i run the command line it works but in dynamical mode it doesn't work and identifies $tag_address in this line $xml->$tag_address=$value; as a string,not as an address. what should i do? TNX

Matt
  • 22,721
  • 17
  • 71
  • 112
S.Faraji
  • 97
  • 2
  • 13
  • Why doesn't it "work"? Is there any error or something? – Voitcus May 27 '13 at 07:44
  • When i give address manually and write $xml->system_settings->settings->hostname = $value; it works and assigns value to this address,but when i give address dynamically such as $xml->$tag_address=$value; it dosn't identify address and identify $tag_address as a string. – S.Faraji May 27 '13 at 07:52
  • Shouldn't this be sth like `write_xml("root->system_settings->settings->hostname",'Helloooooooo');`? (change `root` to your highest-level node name) – Voitcus May 27 '13 at 07:55
  • No,it isn't my problem.When i write the function: system_settings->settings->hostname",'Helloooooooo'); function write_xml($tag_address,$value) { $xml = simplexml_load_file("test.xml") or die("Error: Cannot create object"); $xml->$tag_address=$value; $xml->asXML("test.xml"); } ?> it takes $tag_address as a string,but i want that it realizes that address and assign 'hello' to that. – S.Faraji May 27 '13 at 08:02

2 Answers2

0

The solution is not that easy.

The easiest, but least secure, is to use eval() function so you can write something like this:

eval('$xml'.$tag_address.' = $value;'); // note ' as quotation marks

The most correct way can be that you split your text and create a chained object manually. You can't just refer to all chained elements in one string, but you can do this step-by-step with one element.

For example something like

$splitted_text = explode('->', $tag_address);
$node = $xml;
foreach($splitted_text as $object)
  $node = &$node -> {$object};
// at the moment $node = $xml->system_settings->settings->hostname
$node = $value;
$xml->asXML("test.xml");

should work. I haven't tested it, but the idea is that in each iteration you prepare $node variable going deeper into the $xml variable. At the end you modify only the $node, but as objects are only references, so $xml should change accordingly.

This example assumes that there is no -> in the beginning of $tag_address. If it is, there would be a problem with explode() function because this would create empty string as the first element of the $splitted_text array.

So you might need to remove this empty element or apply calling as

 write_xml("system_settings->settings->hostname",'Helloooooooo');

without the first ->.

Voitcus
  • 4,463
  • 4
  • 24
  • 40
  • Thank you Voitcus,is there the other solution that you suggest me to resolve this problem?This way is so good but it repeats information on the xml file,if it's possible for you please suggest the other way.TNX – S.Faraji May 27 '13 at 08:54
  • Well, the structure itself is not clear. As your `write_xml` function opens, manipulates and then closes the file, you have no access from outside. Personally I would make one function to return XML object from file, the other to manipulate (adding, deleting keys etc.) and the last to save & close. Not functions, but object methods maybe. But if your program does only store hostname it would be a useless effort. But for your problem itself, I don't see any better solution (but don't say there aren't any); IMO all others would be modifications of these two. – Voitcus May 27 '13 at 09:00
  • Ok,i have tested it,in your code we have $node that after foreach it has the address,but it hasn't,i have printed $node and i isn't the address. – S.Faraji May 27 '13 at 09:36
  • You are right, one reference operator `&` was missing in the `foreach` loop - the `$node` should refer to the appropriate `$xml` node. I've created a [working fiddle](http://phpfiddle.org/main/code/8w4-mqu) for you – Voitcus May 27 '13 at 09:47
  • unfortunately,it doesn't work :( the line $node = $value; dosn't work,i mean $value isn't assign to that address. :( – S.Faraji May 27 '13 at 10:02
  • I mean before the line $node = $value address is in $node,but after that line $node changes to 'localhost' and hasn't address,node becomes a simple variable. – S.Faraji May 27 '13 at 10:27
  • So you need to use `&` operator. Note this `&` sign before `$node`: `$node = &$node -> {$object};` It's working in the fiddle. – Voitcus May 27 '13 at 10:39
  • Yes,you told using &sing in example code ,i wrote that but as i said after foreach where you wrote command line i have address in $node but after the line $node=$value ,value assign to node not to that address – S.Faraji May 27 '13 at 10:51
  • You can try `$node = &$xml` before `foreach`. If this won't help, I'm afraid I can't help you. This could be with SimpleXML object issue. – Voitcus May 27 '13 at 11:23
0

Use XPath to select the node, then update the value. For that, you need the proper systax for your tag address.

write_xml("system_settings/settings/hostname", 'Helloooooooo');

function write_xml($tag_address, $value)
{
    $xml         = simplexml_load_file('test.xml') or die("Error: Cannot create object");
    $nodes       = $xml->xpath($tag_address);
    $nodes[0][0] = $value;
    $xml->asXML('test.xml');
}
nibra
  • 3,958
  • 2
  • 20
  • 34