In your case I would not use the simplexml iterator because the problem you've got is that when you remove an element while you iterate over it, the iteration breaks as the element node has gone away. So the second element becomes the first after the first has been removed. Then the iterator goes to the second which now has been the third earlier.
Instead, you could just delete two times the first element:
$xml = simplexml_load_string($string);
for ($remove = 2; $remove--;)
{
unset($xml->example[0]);
}
That will give you:
<?xml version="1.0"?>
<root>
<example>
<thing>3</thing>
<somethingelse>3</somethingelse>
</example>
</root>
The problem with this approach is that you can not generalize it. It is better to first create an array with the elements to remove, then iterate over that array and remove one element after the other.
An easy way to create such an array with simplexml is either iterator_to_array()
or the SimpleXMLElement::xpath()
method. As you used xml_splice()
as a mock in your question, I would assume you want to see the array variant first:
$examples = $xml->example;
$elements = iterator_to_array($examples, false);
array_splice($elements, 2, 3);
This puts all example elements that should be delete into $elements
. All that is left to do is to remove those. In SimpleXML this requires a simplexmlelement-self-reference:
foreach($elements as $element)
{
unset($element[0]);
}
As you can see, to remove the $element
node from the $xml
document, it is unset by its first offset (0). If you would add a var_dump right after it like:
unset($element[0]);
var_dump($element);
You would see this warning showing you the element-node has been removed:
Warning: var_dump(): Node no longer exists
The output is like you now might have expected:
<?xml version="1.0"?>
<root>
<example>
<thing>3</thing>
<somethingelse>3</somethingelse>
</example>
</root>
for the variant with xpath please see my answer at the related question: