PHP用dom删除多个元素

时间:2014-01-08 16:14:36

标签: php xml domdocument

我正在尝试使用DOM Document删除php中的多个元素,但它不起作用,因为我希望它能够工作。

<iPhone>
<enAttentePush>
  <UDID>dd6fc8032f0bf4c4b3a9c60f523900c9ad463b620a83b6473eda9a12b2c9d47f</UDID>
  <Message>someDataHere</Message>
</enAttentePush>

<enAttentePush>
  <UDID>dd6fc8032f0bf4c4b3a9c60f523900c9ad463b620a83b6473eda9a12b2c9d47f</UDID>
  <Message>someDataHere</Message>
</enAttentePush>
</iPhone>

我想循环到我的xml文档中,然后擦除所有元素以获取空文件。

以下是我在php中所做的事情:

$doc = new DOMDocument;

$doc->load('$myFile'); 
$domNodeList = $doc->getElementsByTagName('enAttentePush'); 
$arraySeen = array(); 
$arrayBug = array(); 

foreach ($domNodeList as $domElement)
{
        //echo('loop / ');
  $tempArray = array(); 

  $aps = $domElement->getElementsByTagName('Message')->item(0)->nodeValue;
  $udid = $domElement->getElementsByTagName('UDID')->item(0)->nodeValue; 
  if (!in_array($udid, $arraySeen))
  {         
      $tempArray[]=$aps; 
      $tempArray[]=$udid; 
      $arrayBug[]=$tempArray;
     $arraySeen[]=$udid; 
   }

   echo("-- removed -- ");
   $domElement->parentNode->removeChild($domElement); 
  }

它只删除一个节点,一般是最后一个节点。

我怎样才能循环思考我的节点并在每次看到节点时删除它?

非常感谢。

3 个答案:

答案 0 :(得分:3)

getElementsByTagName()返回“live”迭代器,当您从列表中删除元素时,列表会更改。您可以将迭代器转换为数组以获取列表的副本。

$xml = <<<'XML'
<iPhone>
<enAttentePush>
  <UDID>dd6fc8032f0bf4c4b3a9c60f523900c9ad463b620a83b6473eda9a12b2c9d47f</UDID>
  <Message>someDataHere</Message>
</enAttentePush>
<enAttentePush>
  <UDID>dd6fc8032f0bf4c4b3a9c60f523900c9ad463b620a83b6473eda9a12b2c9d47f</UDID>
  <Message>someDataHere</Message>
</enAttentePush>
</iPhone>
XML;

$dom = new DOMDocument();
$dom->loadXml($xml);

$nodes = iterator_to_array($dom->getElementsByTagName('enAttentePush'));
foreach ($nodes as $node) {
  $node->parentNode->removeChild($node);
}

echo $dom->saveXml();

输出:

<?xml version="1.0"?>
<iPhone>


</iPhone>

更简单的方法是将原始文档中的文档元素复制到新文档中 之一:

$xml = <<<'XML'
<iPhone>
<enAttentePush>
  <UDID>dd6fc8032f0bf4c4b3a9c60f523900c9ad463b620a83b6473eda9a12b2c9d47f</UDID>
  <Message>someDataHere</Message>
</enAttentePush>
<enAttentePush>
  <UDID>dd6fc8032f0bf4c4b3a9c60f523900c9ad463b620a83b6473eda9a12b2c9d47f</UDID>
  <Message>someDataHere</Message>
</enAttentePush>
</iPhone>
XML;

$source = new DOMDocument();
$source->loadXml($xml);

$target = new DOMDocument();
$target->appendChild(
  $target->importNode($source->documentElement, FALSE)
);

echo $target->saveXml();

输出:

<?xml version="1.0"?>
<iPhone/>

要删除特定节点,请使用Xpath选择它们。这允许复杂的条件。

$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);

$nodes = $xpath->evaluate('/*/enAttentePush');
foreach ($nodes as $node) {
  $node->parentNode->removeChild($node);
}

echo $dom->saveXml();

答案 1 :(得分:2)

最近我必须在自己的网站上执行此操作,并发现如果将数组中的元素排队,则可以在此之后轻松删除它们。这是一个使用的小片段,希望它可以帮助你:

$doc = new DOMDocument;

$doc->load('$myFile');
$domNodeList = $doc->getElementsByTagName('enAttentePush');

$domArray = array(); //set up an array to catch all our nodes

foreach($domNodeList as $dom) {
    $domArray[] = $dom;
}

// loop through the array and delete each node
foreach($domArray as $node){ 
    $doc->documentElement->removeChild($node);
}

$doc->save('$myFile');

答案 2 :(得分:1)

正如评论中已经提到的,使用while而不是foreach来迭代DOMNodeList:

$i = $domNodeList->length;
while ($i > 0) {
    $i--;
    $domElement = $domNodeList->item($i);
    $domElement->parentNode->removeChild($domElement); 
}