本文旨在解决在使用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()函数,我们将匹配项数组的顺序反转,从而确保从后往前处理匹配项。
注意事项
总结
在使用PHP的DOMDocument和DOMXPath修改DOM结构时,需要特别注意DOM结构的变化对后续操作的影响。通过反向处理匹配项,可以有效地避免因DOM结构改变而导致的错误,确保代码的稳定性和可靠性。此外,还需要关注编码问题、HTML结构和性能优化等方面,以提高代码的质量和效率。
以上就是解决PHP DOMDocument修改导致后续修改错误的问题的详细内容,更多请关注php中文网其它相关文章!
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 //m.sbmmt.com/ All Rights Reserved | php.cn | 湘ICP备2023035733号