Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
解决PHP DOM操作中多次修改文本节点导致的splitText错误_创想鸟

解决PHP DOM操作中多次修改文本节点导致的splitText错误

解决php dom操作中多次修改文本节点导致的splittext错误

在使用PHP DOMDocument和XPath对文本节点进行多次修改(如包裹特定短语)时,因DOM结构变化可能导致splitText()方法报错,尤其是在正向遍历匹配项时。本文将深入分析此问题,并提供核心解决方案:正确解析preg_match_all结果,并采用逆序遍历匹配项的策略,以确保每次修改都不会影响后续操作的偏移量,从而实现对所有目标文本的准确包裹。

问题背景:DOM文本节点多次修改的挑战

在网页内容处理中,我们经常需要识别并修改特定的文本片段,例如将所有出现的品牌名称用标签包裹起来。PHP的DOMDocument和XPath提供了强大的能力来实现这一点。然而,当一个文本节点中存在多个匹配项,并且我们尝试使用DOMText::splitText()方法逐一修改它们时,一个常见的陷阱是,第一次修改会改变文本节点的内部结构,从而使得后续匹配项的偏移量失效,导致splitText()调用失败并抛出Fatal error: Uncaught Error: Call to a member function splitText() on bool错误。

具体来说,DOMText::splitText(offset)方法会在指定偏移量处将当前文本节点一分为二,返回一个新的文本节点(从偏移量开始的部分)。如果我们在一个文本节点上连续进行多次splitText()操作,并且每次操作都基于原始文本的偏移量,那么在第一次splitText()之后,原始文本节点的长度和内容都已改变,后续的偏移量将不再准确,甚至可能指向一个不再存在的文本部分,导致splitText()返回false,进而引发错误。

解决方案:逆序遍历与正确的匹配结果处理

要解决此问题,我们需要采取两种关键策略:

正确解析preg_match_all的结果: preg_match_all函数返回的$matches数组结构包含多个维度。对于我们关心的完整匹配字符串及其偏移量,通常位于$matches[0]中。不正确的遍历(例如,foreach ($matches as $group))可能会导致重复处理或处理不正确的数据。逆序遍历匹配项: 这是解决偏移量失效问题的核心。如果我们从文本节点的末尾向开头处理匹配项,每次修改(例如,将文本节点拆分并插入)只会影响当前修改点“之前”的DOM结构。这意味着,对于尚未处理的、位于当前修改点“之后”的匹配项,它们的偏移量仍然相对于原始文本节点是准确的。

详细步骤与示例代码

以下是基于原始问题的代码,并应用上述解决方案后的修正版本。我们将专注于foreach ($text as $node)循环内部的修改逻辑。

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

/** * 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_OFFSET_CAPTURE 捕获匹配项的偏移量             */            preg_match_all("/(C.? ?C.?(?:JM| Johnson (?:&|&|&|and) Malhotra)(?: Engineers, LTD.?|, P.?C.?)?)/i", $node->textContent, $matches, PREG_OFFSET_CAPTURE);            /**             * 确保有匹配项才进行处理             * 逆序遍历匹配项,以避免DOM修改导致的偏移量失效问题             * $matches[0] 包含所有完整匹配的字符串及其偏移量             */            $group = array_reverse($matches[0]); // 关键:逆序遍历 $matches[0]            foreach ($group as $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                 * splitText(offset) 会将当前节点在 offset 处分割,                 * 并返回从 offset 开始的新节点。                 * 原节点会保留 offset 之前的部分。                 */                $word  = $node->splitText($offset);                /**                 * 再次调用 splitText,从 $word 节点的开头(即原匹配项的开头)                 * 分割出匹配项本身。                 * $after 节点将包含匹配项之后的部分。                 */                $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         * 提取 body 内容,去除 html/body 包装         */        $content = implode(array_map([$DOM->documentElement->ownerDocument, "saveHTML"], iterator_to_array($DOM->documentElement->childNodes)));        // 如果需要更精确地获取内的内容,可以查询body节点        // $body = $XPath->query('//body')->item(0);        // if ($body) {        //     $content = '';        //     foreach ($body->childNodes as $child) {        //         $content .= $DOM->saveHTML($child);        //     }        // }    }    return $content;}// add_filter("ccjm_final_output", "ccjm_branding_filter"); // 如果是WordPress环境,则需要此行

代码修改要点:

移除冗余循环: 原代码中的 foreach ($matches as $group) 是不必要的,因为$matches数组的第一个元素$matches[0]已经包含了所有完整的匹配项及其偏移量。逆序遍历: 将$matches[0]通过array_reverse()函数进行逆序处理。foreach ($group as $match)现在会从文本的末尾匹配项开始处理。移除break: 原代码中的break语句导致只处理了每个文本节点的第一个匹配项,现在可以安全移除,以确保所有匹配项都被处理。

结果示例

使用提供的示例内容:

C.C. Johnson & Malhotra, P.C. (CCJM) was an integral member of a large Design Team for a 16.5-mile-long Public-Private Partnership (P3) Purple Line Project. The east-west light rail system extends from New Carrollton in PG County, MD to Bethesda in MO County, MD with 21 stations and one short tunnel. CCJM was Engineer of Record (EOR) for the design of eight (8) Bridges and design reviews for 35 transit/highway bridges and over 100 retaining walls of different lengths/types adjacent to bridges and in areas of cut/fill. CCJM designed utility structures for 42,000 LF of relocated water mains and 19,000 LF of relocated sewer mains meeting Washington Suburban Sanitary Commission (WSSC), Md Dept of Transportation (MDOT) MTA, and Local Standards.

经过修正后的代码处理,输出结果将如下所示,所有匹配的短语都被正确地包裹在标签中:

C.C. Johnson & Malhotra, P.C. (CCJM) was an integral member of a large Design Teamfor a 16.5-mile-long Public-Private Partnership (P3) Purple Line Project.The east-west light rail system extends from New Carrollton in PG County,MD to Bethesda in MO County, MD with 21 stations and one short tunnel.CCJM was Engineer of Record (EOR) for thedesign of eight (8) Bridges and design reviews for 35 transit/highwaybridges and over 100 retaining walls of different lengths/types adjacent tobridges and in areas of cut/fill. CCJMdesigned utility structures for 42,000 LF of relocated water mains and19,000 LF of relocated sewer mains meeting Washington Suburban SanitaryCommission (WSSC), Md Dept of Transportation (MDOT) MTA, and LocalStandards.

注意事项与总结

DOM操作的原子性: 每次对DOM树的修改都可能影响其结构。当涉及到文本节点的拆分和替换时,这一点尤为重要。splitText()的返回类型: 务必检查splitText()的返回值。如果偏移量无效,它可能返回false,导致后续对返回值的操作(如$word->splitText($length))失败。性能考量: 对于非常大的HTML文档和大量的文本节点,DOMDocument的操作可能会消耗较多的内存和CPU资源。在生产环境中,应进行性能测试。HTML解析: DOMDocument::loadHTML()在解析非标准或格式不佳的HTML时可能会遇到问题。使用libxml_use_internal_errors(true)和libxml_clear_errors()是一种常见的处理方式,但仍需确保输入HTML的质量。

通过采用逆序遍历匹配项的策略,我们能够有效地规避PHP DOMDocument在处理单个文本节点内多个修改时所面临的偏移量失效问题,从而实现稳健且准确的文本内容转换。理解DOM操作的底层机制是编写高效且无错代码的关键。

以上就是解决PHP DOM操作中多次修改文本节点导致的splitText错误的详细内容,更多请关注创想鸟其它相关文章!

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

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
PHP 文件读写操作:读取、处理与写入成绩数据
上一篇 2025年12月11日 08:28:53
解决PHP DOMDocument修改导致后续修改错误的问题
下一篇 2025年12月11日 08:29:01

相关推荐

  • 利用AWS Pinpoint高效发送注册验证码(OTP)教程

    利用AWS Pinpoint高效发送注册验证码(OTP)教程利用AWS Pinpoint高效发送注册验证码(OTP)教程利用AWS Pinpoint高效发送注册验证码(OTP)教程利用AWS Pinpoint高效发送注册验证码(OTP)教程

    本文旨在指导开发者如何高效利用AWS Pinpoint服务发送用户注册验证码(OTP),解决传统AWS SNS在处理动态、未预注册手机号时的局限性。我们将深入探讨Pinpoint作为首选方案的优势,提供具体实现步骤和代码示例,并分享最佳实践,确保OTP消息的可靠、快速送达。 理解注册验证码(OTP)…

    2026年9月25日 • 用户投稿
    000
  • 2025拍照最强的手机排名:最佳夜景拍照手机

    2025拍照最强的手机排名:最佳夜景拍照手机2025拍照最强的手机排名:最佳夜景拍照手机2025拍照最强的手机排名:最佳夜景拍照手机2025拍照最强的手机排名:最佳夜景拍照手机

    随着用户对智能手机摄影性能的要求日益提高,长焦拍摄能力逐渐成为继主摄像头之后影响购机决策的重要因素。尤其是在演唱会、旅行记录、夜间远摄等使用场景中,出色的长焦表现能够显著提升成像清晰度与画面质感。当前市场上,多款旗舰机型在长焦技术方面实现了突破性进展,其中vivo x300 pro、三星galaxy…

    2026年9月25日 • 用户投稿
    000
  • Win10系统下战网无法安装怎么办?

    Win10系统下战网无法安装怎么办?Win10系统下战网无法安装怎么办?Win10系统下战网无法安装怎么办?Win10系统下战网无法安装怎么办?

    战网无法安装怎么处理?当大家遇到战网客户端无法安装的情况时,应该怎么办呢?毕竟组队开黑的小伙伴还在等你。其实,这种现象通常是因为权限问题或是注册表中有之前的残留数据造成的。经过多次尝试,小编终于找到了一个有效的解决方案,接下来就为大家详细讲解具体的操作步骤。 1,按下Ctrl+Alt+Delete组…

    2026年9月25日 • 用户投稿
    000
  • 如何提高debian readdir的并发处理能力

    如何提高debian readdir的并发处理能力如何提高debian readdir的并发处理能力如何提高debian readdir的并发处理能力如何提高debian readdir的并发处理能力

    提升 Debian 系统 readdir 并发处理能力,需要综合考虑文件系统、内核参数、应用程序优化和并行处理技术等多个方面。以下是一些实用建议: 一、选择高效的文件系统 Debian 默认的 ext4/ext3 文件系统性能良好,但对于高并发场景,可以考虑以下选择: XFS: 尤其适用于存储大量文…

    2026年9月25日 • 用户投稿
    100
  • 疑似华为阔比例大折叠曝光:采用7.6-7.7英寸14:10屏幕

    疑似华为阔比例大折叠曝光:采用7.6-7.7英寸14:10屏幕疑似华为阔比例大折叠曝光:采用7.6-7.7英寸14:10屏幕疑似华为阔比例大折叠曝光:采用7.6-7.7英寸14:10屏幕疑似华为阔比例大折叠曝光:采用7.6-7.7英寸14:10屏幕

    9月28日,有数码博主爆料称,疑似华为下一代阔比例大折叠屏手机mate x7正在测试中。该机采用展开后尺寸为7.6-7.7英寸,并采用14:10的比例。该博主称,新机将硬刚苹果折叠屏手机。 华为Mate X6 据CNMO了解,华为Mate X7有望在今年11月份与Mate 80系列一同亮相。在核心性…

    2026年9月25日 • 用户投稿
    100
  • 如何自定义debian readdir的输出格式

    如何自定义debian readdir的输出格式如何自定义debian readdir的输出格式如何自定义debian readdir的输出格式如何自定义debian readdir的输出格式

    本文介绍几种在Debian系统中自定义readdir输出格式的方法,readdir是用于读取目录内容的系统调用。 方法一:使用opendir和readdir函数 以下C程序演示如何使用opendir和readdir函数读取目录并自定义输出: #include #include #include #i…

    2026年9月25日 • 用户投稿
    400
  • 【新手入门】使用ERNIE-4.5-0.3B-Paddle从原始文本构建知识图谱

    1. 概述 本文将探讨如何使用ernie-4.5-0.3b-paddle模型从原始文本构建知识图谱。通过结合大语言模型(llm)和检索增强生成(rag)技术实现文本生成,帮助我们从非结构化数据中高效提取实体和关系信息。 2. 什么是知识图谱? 2.1 基本概念 知识图谱是一种语义网络,它表示和连接现…

    2026年9月25日
    000
  • 解决Android Studio Gradle构建问题的网络仓库配置指南

    解决Android Studio Gradle构建问题的网络仓库配置指南解决Android Studio Gradle构建问题的网络仓库配置指南解决Android Studio Gradle构建问题的网络仓库配置指南解决Android Studio Gradle构建问题的网络仓库配置指南

    本文旨在解决Android Studio项目中因网络限制导致的Gradle构建失败问题,特别是“插件未找到”等错误。核心解决方案是通过配置替代的Maven仓库(如阿里云镜像)来绕过网络障碍,确保Gradle能够成功解析和下载所需的插件与依赖,从而恢复项目的正常构建。 1. 问题背景与常见症状 在an…

    2026年9月25日 • 用户投稿
    000
  • AI Overviews适合初学者使用吗 功能易用性与学习曲线评估

    AI Overviews适合初学者使用吗 功能易用性与学习曲线评估AI Overviews适合初学者使用吗 功能易用性与学习曲线评估AI Overviews适合初学者使用吗 功能易用性与学习曲线评估AI Overviews适合初学者使用吗 功能易用性与学习曲线评估

    AI Overviews作为一项新兴功能,许多初学者对其适用性感到好奇。本文旨在评估AI Overviews对于初学者而言是否友好,将从功能易用性和学习曲线两个方面进行深入探讨。文章会详细解析其操作流程,帮助用户理解并掌握如何有效地使用这项功能,从而解决标题中关于其适合初学者使用的问题。 ☞☞☞AI…

    2026年9月25日 • 用户投稿
    200
  • MAC怎么快速切换不同的音频输出设备_Mac菜单栏音量图标切换声音输出

    MAC怎么快速切换不同的音频输出设备_Mac菜单栏音量图标切换声音输出MAC怎么快速切换不同的音频输出设备_Mac菜单栏音量图标切换声音输出MAC怎么快速切换不同的音频输出设备_Mac菜单栏音量图标切换声音输出MAC怎么快速切换不同的音频输出设备_Mac菜单栏音量图标切换声音输出

    通过菜单栏音量图标可快速切换音频输出设备,点击音量图标并选择目标设备即可生效;2. 使用快捷键与自动化工具如Keyboard Maestro或快捷指令创建AppleScript脚本,一键切换指定设备;3. 进入系统设置→声音→输出,手动选择设备,适用于初次配置或排查问题。 如果您在Mac上连接了多个…

    2026年9月25日 • 用户投稿
    100
  • Gemini是否能导出成思维导图 AI生成内容结构化展示方式详解

    Gemini是否能导出成思维导图 AI生成内容结构化展示方式详解Gemini是否能导出成思维导图 AI生成内容结构化展示方式详解Gemini是否能导出成思维导图 AI生成内容结构化展示方式详解Gemini是否能导出成思维导图 AI生成内容结构化展示方式详解

    针对“gemini是否能导出成思维导图 ai生成内容结构化展示方式详解”这一问题,本文将详细阐述如何利用gemini生成有助于构建思维导图的结构化内容,并介绍如何配合外部工具完成思维导图的制作。您将了解到gemini作为一款大型语言模型,其主要输出形式是文本。它并不具备直接生成或导出图形化思维导图文…

    2026年9月25日 • 用户投稿
    000
  • 统一解析ISO Zoned Date-Time格式的日期字符串

    统一解析ISO Zoned Date-Time格式的日期字符串统一解析ISO Zoned Date-Time格式的日期字符串统一解析ISO Zoned Date-Time格式的日期字符串统一解析ISO Zoned Date-Time格式的日期字符串

    本教程详细阐述如何在Java 8+中使用java.time API统一解析看似不同但实则遵循ISO 8601扩展ISO_ZONED_DATE_TIME格式的日期字符串。通过ZonedDateTime的直接解析能力和OffsetDateTime结合DateTimeFormatter.ISO_ZONED…

    2026年9月25日 • 用户投稿
    000
  • 360极速浏览器收藏夹在哪个文件夹_书签数据文件本地存储路径

    360极速浏览器收藏夹在哪个文件夹_书签数据文件本地存储路径360极速浏览器收藏夹在哪个文件夹_书签数据文件本地存储路径360极速浏览器收藏夹在哪个文件夹_书签数据文件本地存储路径360极速浏览器收藏夹在哪个文件夹_书签数据文件本地存储路径

    首先定位360极速浏览器的书签文件,该文件通常存储在%LOCALAPPDATA%360ChromeChromeUser DataDefault目录下,查找名为Bookmarks和Bookmarks.bak的文件即可获取当前及备份的收藏夹数据。 如果您需要找回或备份360极速浏览器的收藏夹数据,可能需…

    2026年9月25日 • 用户投稿
    100
  • 怎样通过Nginx日志定位网站问题

    怎样通过Nginx日志定位网站问题怎样通过Nginx日志定位网站问题怎样通过Nginx日志定位网站问题怎样通过Nginx日志定位网站问题

    Nginx日志是网站故障排查的利器,它主要包含访问日志和错误日志两部分。本文将指导您如何利用这两类日志高效定位问题。 一、访问日志 (access log) 访问日志记录了所有对网站的请求信息,包括客户端IP、请求时间、URL、HTTP状态码等关键数据。 常用字段说明: $remote_addr:客…

    2026年9月25日 • 用户投稿
    100
  • 使用Apache POI处理日期显示为””的解决方案

    使用Apache POI处理日期显示为””的解决方案使用Apache POI处理日期显示为””的解决方案使用Apache POI处理日期显示为””的解决方案使用Apache POI处理日期显示为””的解决方案

    在使用Apache POI导出Excel时,日期(特别是早期年份)显示为”####”通常是由于单元格宽度不足以完整显示日期值所致。本文将深入探讨这一常见问题,并提供通过调整单元格宽度来有效解决此问题的具体方法和示例代码,确保日期数据能够正确无误地呈现。 问题描述:Apache…

    2026年9月25日 • 用户投稿
    000
  • 曝苹果内部不看好 iPhone Air 备货量仅占全系列 10%

    曝苹果内部不看好 iPhone Air 备货量仅占全系列 10%曝苹果内部不看好 iPhone Air 备货量仅占全系列 10%曝苹果内部不看好 iPhone Air 备货量仅占全系列 10%曝苹果内部不看好 iPhone Air 备货量仅占全系列 10%

    iPhone Air 9 月 17 日,CNMO 了解到,作为苹果史上最为轻薄的智能手机,iPhone Air 的预售表现远逊于同系列其他机型。即便苹果仅为其分配了整体备货量的 10%,该机型仍未实现售罄。 据 CNMO 消息,iPhone 17 系列在首个预购周末交出亮眼成绩,整体需求超越去年同期…

    2026年9月25日 • 用户投稿
    000
  • sublime怎么安装字体_sublime字体安装方法

    sublime怎么安装字体_sublime字体安装方法sublime怎么安装字体_sublime字体安装方法sublime怎么安装字体_sublime字体安装方法sublime怎么安装字体_sublime字体安装方法

    先安装字体到操作系统,再在Sublime Text设置中指定字体。1. 将.ttf或.otf字体文件安装至系统:Windows右键安装,macOS用字体册,Linux复制到~/.fonts并刷新缓存。2. 在Sublime的Preferences→Settings用户配置中添加”font…

    2026年9月25日 • 用户投稿
    000
  • 深入解析:Java中不同ISO时区日期字符串的统一解析策略

    深入解析:Java中不同ISO时区日期字符串的统一解析策略深入解析:Java中不同ISO时区日期字符串的统一解析策略深入解析:Java中不同ISO时区日期字符串的统一解析策略深入解析:Java中不同ISO时区日期字符串的统一解析策略

    本文探讨了如何在Java中统一解析来自API响应的多种ISO时区日期字符串,即使它们在表示上略有差异。核心方法是利用Java 8及更高版本提供的java.time包中的ZonedDateTime或OffsetDateTime类,并结合DateTimeFormatter.ISO_ZONED_DATE_…

    2026年9月25日 • 用户投稿
    000
  • 不止于“芯”,更在于体验:至像 Z35 国产芯系列打印机引领行业新趋势

    不止于“芯”,更在于体验:至像 Z35 国产芯系列打印机引领行业新趋势不止于“芯”,更在于体验:至像 Z35 国产芯系列打印机引领行业新趋势不止于“芯”,更在于体验:至像 Z35 国产芯系列打印机引领行业新趋势不止于“芯”,更在于体验:至像 Z35 国产芯系列打印机引领行业新趋势

    在“国产替代”趋势席卷各个领域的今天,打印机这一曾长期被海外品牌垄断的细分市场,也迎来了属于“中国智造”的高光时刻。过去,国际厂商凭借技术积累与先发优势,牢牢掌控着国内打印市场的主动权——从核心元器件到整机系统,国内企业往往受制于人,难以真正掌握话语权。 如今,随着本土技术实力的跃升和产业链的日趋成…

    2026年9月25日 • 用户投稿
    600
  • 一抹澄霞 万般雅韵 心系天下三星W26全新配色正式亮相

    一抹澄霞 万般雅韵 心系天下三星W26全新配色正式亮相一抹澄霞 万般雅韵 心系天下三星W26全新配色正式亮相一抹澄霞 万般雅韵 心系天下三星W26全新配色正式亮相一抹澄霞 万般雅韵 心系天下三星W26全新配色正式亮相

    10月11日,三星电子携手中国电信举办心系天下三星w系列新品发布会,隆重推出新一代超高端智能手机——心系天下三星w26。自2008年问世以来,心系天下三星w系列秉持“传承、创新、尊贵、思仁”的理念,历代产品均凝结时代精神,成为广大精英雅士的心之所向。心系天下三星w26在延续尊贵基因的基础上,以更轻盈…

    2026年9月25日 • 用户投稿
    000

发表回复

登录后才能评论
关注微信