-1

Is it possible to remove n number of xml elements from a xml document so that

<root>
<example>
<thing>1</thing>
<somethingelse>1</somethingelse>
</example>
<example>
<thing>2</thing>
<somethingelse>2</somethingelse>
</example>
<example>
<thing>3</thing>
<somethingelse>3</somethingelse>
</example>
</root>

could become

<root>
<example>
<thing>3</thing>
<somethingelse>3</somethingelse>
</example>
</root>

e.g. xml_splice($xml,2,3)

After searching the documentation I cant find a simple way to do this in simpleXML but there something else i can use? or am i stuck with writing my own function using $xmlIterator->next();

thanks in advance

AttikAttak
  • 797
  • 4
  • 12
  • 20

1 Answers1

1

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:

Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836