使用unset()删除XML中的节点; PHP /使用simplexml_load_file

I'm trying to use unset() to delete a node in an XML using PHP and can't figure out what is going on here. It doesn't seem to work correctly and I've seen a lot of other questions of similar nature on here but they don't seem to address this issue directly. Here's what my XML looks like:

<?xml version="1.0" encoding="UTF-8"?>
<data>
    <user>
        <name>Test Name 1</name>
        <email>test@test.com</email>
        <spouse/>
    </user>
    <user>
        <name>Test Name 2</name>
        <email>anotherone@test.com</email>
        <spouse>Test Name 3</spouse>
    </user>
</data>    

My loop that I'm using is like this:

url = 'data/users.xml';
$xml = simplexml_load_file($url);

foreach($xml->user as $theUser){
    if($theUser->email[0]=="test@test.com"){
        echo "test";
        unset($theUser);
    }
}

When the e-mail matches "test@test.com" I want to be able to delete that whole user node. It seems that this should work but I can't figure out why it wouldn't? Any help would be greatly appreciated. Thank you!

SimpleXML is fine, no need to switch to DOM, unset() is working fine, if you do it right:

unset($theUser[0]);

see it working: https://eval.in/228773

However there will be a problem with your foreach() if you delete a node mid-loop.

I suggest to use xpath() instead of a loop, IMO elegant and the code is much simpler.

$users = $xml->xpath("/data/user[email='test@test.com']");

will create an array of all <user> with that email-address.

unset($users[0][0]);

will delete the first user in that array.

foreach ($users as $user) unset($user[0]);

will delete the whole array.

see this in action: https://eval.in/228779

SimpeXML is not really meant for changing to the XML structure. Just a simple way of reading the XML.

If you want to manipulate the XML structure you should use the dom functions and more specifically the dom_import_simplexml. This function allows you to import a SimpleXML element and turn it into a DomElement that can be used for manipulation and that includes deletion.

Here is a code sample that solves your problem and demonstrates the usage of dom_import_simplexml.

<?php

$xmlData = '<?xml version="1.0" encoding="UTF-8"?>
<data>
    <user>
        <name>Test Name 1</name>
        <email>test@test.com</email>
        <spouse/>
    </user>
    <user>
        <name>Test Name 2</name>
        <email>anotherone@test.com</email>
        <spouse>Test Name 3</spouse>
    </user>
</data>';

$xml = simplexml_load_string($xmlData);

foreach($xml->user as $theUser){
    if($theUser->email == 'test@test.com'){
        $dom = dom_import_simplexml($theUser);
        $dom->parentNode->removeChild($dom);
    }
}

echo $xml->asXml();

When reading this code you might be thinking why this works since we dont save the new structure anywhere after we have executed the removeChild function. This works because the DOM functions does not create copies of the underlying objects but instead manipulates them directly.

Result

<?xml version="1.0" encoding="UTF-8"?>
<data>  
    <user>
        <name>Test Name 2</name>
        <email>anotherone@test.com</email>
        <spouse>Test Name 3</spouse>
    </user>
</data>