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

心靈之曲
发布: 2025-08-24 23:18:00
原创
762人浏览过

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

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

在使用PHP的DOMDocument和DOMXPath处理HTML内容时,经常需要查找并修改特定的文本节点。一个常见的需求是将某些关键词或短语用<span>标签包裹起来,以便进行样式控制或特殊处理。然而,如果在循环中修改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 `<html>` wrapper required for parsing
         */
        $DOM->loadHTML("<?xml encoding='utf-8' ?><html>{$content}</html>", 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>和<body>标签。
  • 性能优化: 对于大型HTML文档,频繁的DOM操作可能会影响性能。可以考虑使用更高效的字符串处理方法,或者使用缓存机制来减少DOM操作的次数。

总结

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

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

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 //m.sbmmt.com/ All Rights Reserved | php.cn | 湘ICP备2023035733号