PHP:递归处理然后从 DOMDocument 中删除 DOMElement

发布于 2024-09-19 06:09:17 字数 922 浏览 8 评论 0原文

我使用 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 并按该顺序删除所有节点,但我有一个从上到下的特定需求。

这里的另一条信息 - 我还在处理文档时向文档添加了一些新节点,以防更改我的选项。

我需要做什么才能让它发挥作用?

I'm using PHP's DOMDocument and related classes to work with XML. The XML contains processing instructions that must be processed in a specific order, from top to bottom, deepest to shallowest.

I'm using a recursive function that takes the entire DOMDocument, then calls itself foreach child node, all the way down.

I need to delete some of these child nodes after I process them. The problem is that as soon as a child node is deleted, it seems the foreach is "out of whack" and I can't delete any more child nodes.

Example XML doc:

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

I need to process inner[@id=3] first, then delete it. Then I need to process instruction[id=2] and delete it. Up until here, everything's fine.

Next I need to process inner[@id=5] and delete it. I can read/process it ok, but when I try to remove it:

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

Nothing happens. It seems that removing the first instruction node has made PHP confused about which elements are contained in the document now.

I know it's possible to process the XML from bottom to top and remove all of the nodes in that order, but I have a specific need to go from top-to-bottom.

One other piece of info here - I'm also adding some new nodes to the document while processing it, in case that changes my options.

What do I need to do to get this to work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

哽咽笑 2024-09-26 06:09:17

许多 DOM 结构在内部只是数组。删除元素会改变情况,因为存储在返回的 NODElist 对象中的键/指针将引用不再存在的数组偏移量,或者包含完全不同的内容。

为了正确处理删除 DOM 节点而不打乱这些不同的指针,您必须从数组的末尾向开头进行操作。不要就地删除节点,而是将它们存储在堆栈类型的结构中,在完成树的任何特定级别上的操作后,您可以将所有内容从堆栈中弹出并进行删除。此时,任何悬空指针都将毫无意义,因为您已经完成了工作。

A lot of the DOM structures are internally just arrays. Deleting elements will shift things around as the keys/pointers stored in returned NODElist objects will refer to array offsets which no longer exist, or contain something completely differnt.

To properly handle deleting DOM nodes without upsetting these various pointers, you have to work from the end of the array towards the beginning. Instead of deleting the nodes in-place, store them in a stack-type structure and after you've completed operations on any particular level of the tree, you can pop everything off the stack and do the deletions then. At this point any dangling pointers will be moot as you've completed your work already.

风铃鹿 2024-09-26 06:09:17

我一定是瞎了。不知怎的,我错过了这里关于这个确切问题的讨论:
http://www.php.net/manual/en/domnode.removechild。 php

对于不必要的混乱表示歉意。

I must be blind. Somehow I missed the discussion here about this exact problem:
http://www.php.net/manual/en/domnode.removechild.php

Apologies for the unnecessary clutter.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文