2

这是我正在处理的 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 号。当它在循环内时,它输出的错误如下:

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

我的代码有什么问题?

4

3 回答 3

2

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

于 2008-10-12T17:52:54.527 回答
1

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

于 2008-10-13T20:39:52.300 回答
1

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

您可能希望首先为每个活动提供一个可以搜索的唯一标识符,例如一个名为“id”的属性(这可能不是真正的 ID。DOM 的 getElementByID() 仅适用于具有 DTD 的 XML,例如一个 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));

希望这有助于您入门。

于 2008-10-15T01:23:14.537 回答