PHP: рекурсивно обработать, а затем удалить DOMElements из DOMDocument - PullRequest
0 голосов
/ 15 сентября 2010

Я использую PHP DOMDocument и связанные с ним классы для работы с XML.XML содержит инструкции по обработке, которые должны обрабатываться в определенном порядке, сверху вниз, от глубины к глубине.

Я использую рекурсивную функцию, которая принимает весь DOMDocument, а затем вызывает себя foreach дочерний узел, все пути вниз.

Мне нужно удалить некоторые из этих дочерних узлов после их обработки.Проблема заключается в том, что как только дочерний узел удаляется, кажется, что foreach «не в порядке», и я больше не могу удалить дочерние узлы.

Пример XML-документа:

<root id="1">
    <instruction id="2">
        <inner id="3"/>
    </instruction>
    <instruction id="4">
        <inner id="5"/>
    </instruction>
</root>

Мне нужно сначала обработать inner[@id=3], а затем удалить его.Затем мне нужно обработать instruction[id=2] и удалить его.До этого момента все в порядке.

Далее мне нужно обработать inner[@id=5] и удалить его.Я могу читать / обрабатывать это нормально, но когда я пытаюсь удалить это:

$parentNode=$inner->parentNode;
$parentNode->removeChild($inner);

Ничего не происходит.Похоже, что удаление первого узла инструкции привело к тому, что PHP запутался в том, какие элементы содержатся в документе.

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

Еще одна часть информации здесь - я также добавляю некоторые новые узлы в документ при обработке его, на случай, если это изменит мои параметры.

Что мне нужно сделать, чтобы это заработало?

Ответы [ 2 ]

2 голосов
/ 16 сентября 2010

Многие структуры DOM внутренне являются массивами. Удаление элементов приведет к смещению, поскольку ключи / указатели, хранящиеся в возвращенных объектах NODElist, будут ссылаться на смещения массива, которые больше не существуют или содержат что-то совершенно иное.

Чтобы правильно обрабатывать удаление узлов DOM без нарушения этих различных указателей, вы должны работать от конца массива до начала. Вместо того, чтобы удалять узлы на месте, сохраняйте их в структуре стекового типа, и после того, как вы выполнили операции на любом конкретном уровне дерева, вы можете вытолкнуть все из стека и затем удалить. На этом этапе любые висячие указатели будут иметь спорный характер, когда вы уже закончили свою работу.

1 голос
/ 15 сентября 2010

Я должен быть слепым. Я почему-то пропустил обсуждение этой проблемы: http://www.php.net/manual/en/domnode.removechild.php

Извинения за ненужный беспорядок.

...