Проблемы с удалением XML-элементов с помощью PHP 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');
?>

Я протестировал процедуру удаления без цикла, используя жестко заданный произвольный идентификатор, и она сработала. Я также протестировал массив $ atvID, и он правильно распечатал выбранные номера идентификаторов. Когда он находится внутри цикла, он выводит ошибку:

Catchable fatal error: Argument 1 passed to DOMNode::removeChild() must be an instance of DOMNode, null given in /directorypath/delete.php on line 9

Что не так с моим кодом?

Я получил ту же ошибку в новой кодовой базе, которую пробовал сегодня. Это начало заставлять меня помещать XML в одну из моих самых ненавистных вещей для отладки.

Talvi Watia 09.07.2010 09:00
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
2
1
6 705
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

элементы DOMNodeList индексируются, начиная с 0; Вам нужно переместить $ count ++ в конец цикла while на шаге вывода.

В дополнение к перемещению $ count ++ в конец цикла while было бы неплохо проверить delete.php, чтобы убедиться, что $ _POST ['activity'] является числовым и находится в указанном диапазоне, просто чтобы убедиться, что на вашей странице нет сообщений о фатальных ошибках.

Как мне сделать проверку?

liewl 14.10.2008 09:10

Сложность DOMNodeLists заключается в том, что они НЕ являются массивами. Если вы удалите узел, список будет переиндексирован. Это приведет к поломке вашего кода, если пользователь выберет более одного элемента для удаления. Если вы выбрали плавание и бег, плавание и футбол будут удалены.

Возможно, вы захотите начать с присвоения каждому действию уникального идентификатора, который вы можете искать, скажем, атрибута с именем 'id' (это, вероятно, не будет настоящим идентификатором. GetElementByID () DOM работает только для XML, у которого есть 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));

Надеюсь, это поможет вам начать работу.

Интересно. Как вы догадались, у меня возникли проблемы с удалением сразу нескольких записей именно из-за переиндексации DOM. Я решил эту проблему более простым способом, я начал удаление с самого большого идентификатора. Это сработало, но ваше решение заставило меня задуматься о xpath, я посмотрю на это.

liewl 16.10.2008 22:06

Другие вопросы по теме