使用PHP DOM删除XML元素的问题

时间:2008-10-12 17:42:14

标签: php xml dom

这是我正在处理的XML文件:

<list>
    <activity>swimming</activity>
    <activity>running</activity>
    <activity>soccer</activity>
</list>

index.php,显示带复选框的活动列表的页面,删除已检查活动的按钮以及添加新活动的字段:

<html>
<head></head>
<body>
<?php
    $xmldoc = new DOMDocument();
    $xmldoc->load('sample.xml', LIBXML_NOBLANKS);

    $count = 0;

    $activities = $xmldoc->firstChild->firstChild;
    //prints the list of activities, with checkboxes on the left for each item
    //the $count variable is the id to each entry
    if($activities!=null){
        echo '<form name=\'erase\' action=\'delete.php\' method=\'post\'>' . "\n";
        while($activities!=null){
            $count++;
            echo "    <input type=\"checkbox\" name=\"activity[]\" value=\"$count\"/>";
            echo ' '.$activities->textContent.'<br/>'."\n";
            $activities = $activities->nextSibling;
        }
        echo '    <input type=\'submit\' value=\'erase selected\'>';
        echo '</form>';
    }
?>
//section used for inserting new entries. this feature is working as expected.
<form name='input' action='insert.php' method='post'>
    insert activity:
    <input type='text name='activity'/>
    <input type='submit' value='send'/>
    <br/>
</form>
</body>
</html>

delete.php,它没有按预期工作:

<?php
    $xmldoc = new DOMDocument();
    $xmldoc->load('sample.xml', LIBXML_NOBLANKS);

    $atvID = $_POST['activity'];

    foreach($atvID as $id){
        $delnode = $xmldoc->getElementsByTagName('activity');
        $xmldoc->firstChild->removeChild($delnode->item($id));
    }

    $xmldoc->save('sample.xml');
?>

我已经使用硬编码的任意id测试了没有循环的删除例程,并且它有效。我还测试了$ atvID数组,它正确打印了所选的id号。当它在循环内部时,这是它输出的错误:

  

可捕获的致命错误:参数1   传递给DOMNode :: removeChild()必须   是DOMNode的一个实例,null给定   在   /directorypath/delete.php   第9行

我的代码出了什么问题?

3 个答案:

答案 0 :(得分:2)

DOMNodeList项的索引从0开始; 您需要在输出步骤中将$ count ++移动到while循环的末尾。

答案 1 :(得分:1)

除了将$ count ++移动到while循环结束之外,最好让delete.php检查以确保$ _POST ['activity']是数字且在指定范围内,只是为了确保页面上没有生成致命错误消息。

答案 2 :(得分:1)

关于DOMNodeLists的棘手问题是它们不是数组。如果删除节点,列表将重新编制索引。如果用户选择多个项目进行删除,这将导致代码中断。如果您选择游泳和跑步,游泳和足球将被删除。

您可能希望首先为每个活动提供一个可以搜索的唯一标识符,例如一个名为“id”的属性(这可能不是真正的ID .DOM的getElementByID()仅适用于具有DTD,就像一个HTML页面。我猜你不想去那里。)

您可能会将XML更新为这样。

<list>
    <activity name="swimming">swimming</activity>
    <activity name="running">running</activity>
    <activity name="soccer">soccer</activity>
</list>

您可以使用这些名称属性而不是$ count作为复选框中的值。

然后,您可以使用xPath查找要在foreach中删除的项目。

$xpath = new DOMXPath($xmldoc);
$xmldoc->firstChild->removeChild($xpath->query("/list/activity[@name='$id']")->item(0));

希望这有助于您入门。