解决PHP DOMDocument修改导致后续修改错误的问题

解决php domdocument修改导致后续修改错误的问题

本文旨在解决在使用PHP的DOMDocument和XPath修改DOM时,由于首次修改导致后续修改出现Call to a member function splitText() on bool错误的问题。通过分析问题原因,提出了一种通过反向处理匹配项来避免修改位置偏移的有效解决方案,并提供了相应的代码示例。

在使用PHP的DOMDocument和DOMXPath处理HTML内容时,经常需要查找并修改特定的文本节点。一个常见的需求是将某些关键词或短语用标签包裹起来,以便进行样式控制或特殊处理。然而,如果在循环中修改DOM结构,可能会遇到一个棘手的问题:首次修改后,后续的查找和修改操作可能会因为DOM结构的改变而出现错误。具体表现为Call to a member function splitText() on bool。

问题分析

该错误通常发生在尝试对已经因为之前的DOM操作而失效的节点执行splitText()方法时。splitText()方法用于将一个文本节点分割成两个节点。当DOM结构发生变化时,原有的节点对象可能不再有效,或者其在DOM树中的位置已经改变,导致splitText()方法无法正确执行。

立即学习“PHP免费学习笔记(深入)”;

解决方案:反向处理匹配项

一个有效的解决方案是反向处理匹配项。这意味着,不要从前往后依次替换找到的匹配项,而是从后往前进行替换。这样,每次修改只会影响当前位置之前的DOM结构,而不会影响尚未处理的匹配项的位置和偏移量。

代码示例

下面是修改后的代码示例,展示了如何反向处理匹配项来避免错误:

/** * Automatically wrap various forms of CCJM in a class for branding purposes * * @param string $content * @return string */function ccjm_branding_filter(string $content): string {    if (! (is_admin() && ! wp_doing_ajax()) && $content) {        $DOM = new DOMDocument();        /**         * Use internal errors to get around HTML5 warnings         */        libxml_use_internal_errors(true);        /**         * Load in the content, with proper encoding and an `` wrapper required for parsing         */        $DOM->loadHTML("{$content}", LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);        /**         * Clear errors to get around HTML5 warnings         */        libxml_clear_errors();        /**         * Initialize XPath         */        $XPath = new DOMXPath($DOM);        /**         * Retrieve all text nodes, except those within scripts         */        $text = $XPath->query("//text()[not(parent::script)]");        foreach ($text as $node) {            /**             * Find all matches, including offset             */            preg_match_all("/(C.? ?C.?(?:JM| Johnson (?:&|&|&|and) Malhotra)(?: Engineers, LTD.?|, P.?C.?)?)/i", $node->textContent, $matches, PREG_OFFSET_CAPTURE);            /**             * Wrap each match in appropriate span             */            $group = array_reverse($matches[0]); // 反转匹配项数组            foreach ($group as $key => $match) {                /**                 * Determine the offset and the length of the match                 */                $offset = $match[1];                $length = strlen($match[0]);                /**                 * Isolate the match and what comes after it                 */                $word  = $node->splitText($offset);                $after = $word->splitText($length);                /**                 * Create the wrapping span                 */                $span = $DOM->createElement("span");                $span->setAttribute("class", "__brand");                /**                 * Replace the word with the span, and then re-insert the word within it                 */                $word->parentNode->replaceChild($span, $word);                $span->appendChild($word);            }        }        /**         * Save changes, remove unneeded tags         */        $content = implode(array_map([$DOM->documentElement->ownerDocument, "saveHTML"], iterator_to_array($DOM->documentElement->childNodes)));    }    return $content;}

关键的修改在于以下这行代码:

$group = array_reverse($matches[0]); // 反转匹配项数组

通过使用array_reverse()函数,我们将匹配项数组的顺序反转,从而确保从后往前处理匹配项。

注意事项

编码问题: 在加载HTML内容时,务必指定正确的编码,避免出现乱码问题。HTML结构: 确保加载的HTML内容具有良好的结构,例如包含和标签。性能优化: 对于大型HTML文档,频繁的DOM操作可能会影响性能。可以考虑使用更高效的字符串处理方法,或者使用缓存机制来减少DOM操作的次数。

总结

在使用PHP的DOMDocument和DOMXPath修改DOM结构时,需要特别注意DOM结构的变化对后续操作的影响。通过反向处理匹配项,可以有效地避免因DOM结构改变而导致的错误,确保代码的稳定性和可靠性。此外,还需要关注编码问题、HTML结构和性能优化等方面,以提高代码的质量和效率。

以上就是解决PHP DOMDocument修改导致后续修改错误的问题的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1292694.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月11日 08:28:58
下一篇 2025年12月11日 08:29:11

相关推荐

发表回复

登录后才能评论
关注微信