在php中运行的单个脚本中,不会删除所有xml标记

时间:2012-08-07 18:18:52

标签: php xml

我有以下xml:

<?xml version="1.0" encoding="utf-8"?>
<server>
  <gcm regId="APA91-yySYdx_Ydvkl2pQNB54yDpJRq4SnWvJCpsaCm6hT3LlXqP1S-3uTiXlXwylPKmrFSZbsA" email="mozi"/>
  <conversation ip="mozi1" email="mozi">
    <chat>abc</chat>
  </conversation>
  <conversation ip="mozi1" email="mozi">
    <chat>abc</chat>
  </conversation>
  <conversation ip="mozi1" email="mozi">
    <chat>abc</chat>
  </conversation>
  <conversation ip="mozi1" email="mozi">
    <chat>abc</chat>
  </conversation>
  <conversation ip="mozi1" email="mozi">
    <chat>abc</chat>
  </conversation>
</server>

我想删除conversation所有email=mozi个标签。

我是通过以下代码完成的。

public function DeleteConversation()
{
    $conv=$this->xmlDom->getElementsByTagName("conversation");

    foreach ($conv as $conversation) 
    {
        if ($conversation->getAttribute('email') == $this->adminEmail) 
        {
            $this->xmlDom->documentElement->removeChild($conversation);
        }
    }
    $this->SaveChanges();
}

现在,当我运行脚本并调用此函数时。循环只能工作3次。它只删除3 records。当我下次运行脚本时,它会删除一条记录,下一次记录一条记录。这就是所有五条记录都被删除的原因。为什么会发生这种情况?

我希望他们一次性删除。请帮忙。

2 个答案:

答案 0 :(得分:2)

使用foreach结合删除DOMNodeList中的元素很麻烦。删除元素后,列表会就地更改,但foreach不会对此进行补偿。

  

DOM中的NodeList和NamedNodeMap对象是实时的;也就是说,对底层文档结构的更改将反映在所有相关的NodeList和NamedNodeMap对象中。

     

- The DOM Structure Model

两种常见的方法是:

  1. 构建要删除的元素集合,然后将其删除

    foreach ($conv as $conversation) 
    {
        if ($conversation->getAttribute('email') == $this->adminEmail) 
        {
            $to_delete[] = $conversation;
        }
    }
    
    foreach ($to_delete as $conversation)
    {
        $conversation->parentNode->removeChild($conversation);
    }
    
  2. 从列表中删除第一个元素,直到不再有

    $conv = $xpath->query('/server/conversation[@email="'.$this->adminEmail.'"]');
    while ($conv->length > 0)
    {
        $conv->item(0)->parentNode->removeChild($conv->item(0));
    }
    

答案 1 :(得分:0)

我认为这是因为你操纵了你正在循环的集合。尝试创建数组的副本,如下所示:

public function DeleteConversation()
{
    $conv=$this->xmlDom->getElementsByTagName("conversation");
    $copy = $conv;

    foreach ($copy as $conversation) 
    {
        if ($conversation->getAttribute('email') == $this->adminEmail) 
        {
            $this->xmlDom->documentElement->removeChild($conversation);
        }
    }
    $this->SaveChanges();
}