Updating XML nodes using SimpleXML adds extra node

I have a very simple script that basically searches an xml file for a node based on the id of another node. I then update the node I found with a new value. For some reason my code is not performing the update. It is actually creating another node within the existing node. Any idea why?

XML:


  <?xml version="1.0" encoding="UTF-8" ?>
- <users>
- <user>
  <id>1</id>
  <firstname>Bob</firstname>
  <lastname>Marley</lastname>
  </user>
- <user>
  <id>2</id>
  <firstname>Bruce</firstname>
  <lastname>Springsteen</lastname>
  </user>
  </users>


PHP Code:


<?php

$file = "officedata.xml";

$xml=simplexml_load_file($file);

foreach ($xml->xpath('//user[id="2"]/lastname') as $desc) {
echo "$desc\
";
$desc->lastname = "Penner";
}

file_put_contents($file, $xml->asXML());

?>


The updated XML looks like this:

  <?xml version="1.0" encoding="UTF-8" ?>
- <users>
- <user>
  <id>1</id>
  <firstname>Bob</firstname>
  <lastname>Marley</lastname>
  </user>
- <user>
  <id>2</id>
  <firstname>Bruce</firstname>
- <lastname>
  Springsteen
  <lastname>Penner</lastname>
  </lastname>
  </user>
  </users>

No, that code outputs:

Springsteen

and that is correct according to your code.

file_put_contents($file, $xml->asXML());

outside the loop?

Isn’t your wrong output correct in the way you do it?

Is it easier to use DOM XML functions like create_element, append_child … ?

I think the result is correct for how I have coded this script. I am just not happy with the result (two lastname tags). Perhaps I will try and drop the node an recreate it…just seems like there should be a better way to update XML via PHP!

  1. I don’t agree. What does that code line do outside the loop? Print out variables and var_dump objects.
  2. Some times it is better easier / more transparent to use DOM functions as indicated in my last post.

You mean something like this?


$file = "officedata.xml";

$xml=simplexml_load_file($file);

foreach ($xml->xpath('//user[id="2"]/lastname') as $desc) {

$dom=dom_import_simplexml($desc);
$dom->nodeValue = "Penner";

}

file_put_contents($file, $xml->asXML());

Which works like a charm…Thanks!