SimpleXML remove multiple nodes by index

时间:2018-05-09 02:45:34

标签: php simplexml

I want to remove specific indexes from an xml file and save it back.

<channel>
  <item>foo</item>
  <item>bar</item>
  <item>baz</item>
  <item>foo</item>
  ...
  <item>foo</item>
  <item>bar</item>
  <item>baz</item>
  <item>foo</item>
</channel>

I have an array of indexes

$indexes_to_remove = array(3,12,17);

I load the file and loop over the indexes and try to unset

$xml = simplexml_load_file('content.xml');

foreach($indexes_to_remove as $id){
    unset($xml->channel->item[(int)$id][0]);
}
file_put_contents('content.xml', $xml->asXML());

But it doesn't work as expected. Items get removed but not the right ones (not all of them). I believe it's because while unsetting the simple xml index gets messed up.

I've looked over existing questions and I've also tried

foreach($indexes_to_remove as $id){
    $result = $xml->xpath( "(//item)[$id]" );
    foreach ( $result as $node ) {
        $dom = dom_import_simplexml($node);
        $dom->parentNode->removeChild($dom);
    }
}
file_put_contents('content.xml', $xml->asXML());

Same result. I can't figure out what I'm doing wrong.

1 个答案:

答案 0 :(得分:0)

尝试这样,

<强> content.xml中

<channel>
  <item>foo</item>
  <item>bar</item>
  <item>3rd value</item>
  <item>foo</item>

  <item>foo</item>
  <item>bar</item>
  <item>baz</item>
  <item>foo</item>

  <item>foo</item>
  <item>bar</item>
  <item>baz</item>
  <item>12th value</item>

  <item>foo</item>
  <item>bar</item>
  <item>baz</item>
  <item>foo</item>

  <item>17th value</item>
  <item>bar</item>
  <item>baz</item>
  <item>foo</item>
</channel>

<强> PHP

$indexes_to_remove = array(3,12,17);
$xml = simplexml_load_file('content.xml', 'SimpleXMLElement');
if($xml->item){
    $rindex = 0;
    foreach($indexes_to_remove as $index){   
        $index += $rindex; // changing index after removed the node
        $dom = $xml->xpath('/channel/item['.$index.']');
        $dom = dom_import_simplexml($dom[0]);   
        $dom->parentNode->removeChild($dom);
        $rindex--;               
    }
}
file_put_contents('content.xml', $xml->asXML());

<强>输出

<channel>
  <item>foo</item>
  <item>bar</item>
  <item>foo</item>

  <item>foo</item>
  <item>bar</item>
  <item>baz</item>
  <item>foo</item>

  <item>foo</item>
  <item>bar</item>
  <item>baz</item>

  <item>foo</item>
  <item>bar</item>
  <item>baz</item>
  <item>foo</item>

  <item>bar</item>
  <item>baz</item>
  <item>foo</item>
</channel>