PHP DOMDocument替换DOM文本仅生效于首个标签问题求助
问题:PHP DOMDocument仅替换每个section下第一个标签内容的问题
我使用PHP DOMDocument遍历一段HTML字符串,希望将每个包含文本值的标签内容替换为自定义Vue插值字符串,但出现问题:仅每个section的第一个标签内容被替换,需要实现所有section内的标签内容都被替换。
原始HTML字符串
$htmlString = "<section> <p>text</p> <p>text</p> </section> <section> <h2>text</h2> <p>text</p> <p>text</p> </section>"
我的实现代码
$dom = new \DOMDocument(); libxml_use_internal_errors(true); $htmlString = mb_convert_encoding($htmlString, 'HTML-ENTITIES', 'UTF-8'); $dom->loadHTML($htmlString); $count = 0; $keyPattern = 'ccpaRights'; foreach ($dom->getElementsByTagName('section') as $section) { // loop through each child of <section> foreach ($section->childNodes as $childNode) { $nodeValue = trim($childNode->nodeValue); if ($nodeValue === '') { continue; } $count = $count + 1; $key = (string) $keyPattern.'Text'.$count; $vueInterpolation = ' {{ $t('.'"'.$key.'"'.' }} '; $newNode = $dom->createElement($childNode->nodeName, $vueInterpolation ); $childNode->parentNode->replaceChild($newNode, $childNode); } } $dom->saveHTML($dom); $dom->save(public_path('/temp/result.html'));
当前错误结果
<section> <p> {{ $t("ccpaRightsText1" }} </p> <p>text</p> </section> <section> <h2> {{ $t("ccpaRightsText2" }} </h2> <p>text</p> <p>text</p> </section>
期望结果
<section> <p> {{ $t("ccpaRightsText1" }} </p> <p> {{ $t("ccpaRightsText2" }} </p> </section> <section> <h2> {{ $t("ccpaRightsText3" }} </h2> <p> {{ $t("ccpaRightsText4" }} </p> <p> {{ $t("ccpaRightsText5" }} </p> </section>
问题原因
$section->childNodes返回的是动态DOMNodeList对象,而非静态数组。当替换节点时,列表的内部索引会实时变化,导致遍历过程跳过后续节点——比如第一个节点被替换后,原第二个节点的索引变为第一个,但遍历指针已移动到下一个位置,直接跳过了它。
解决方案
将动态的DOMNodeList转换为静态数组后再遍历,确保遍历过程不受DOM结构修改的影响。同时修复原代码中Vue插值的语法错误:
修改后的核心代码
foreach ($dom->getElementsByTagName('section') as $section) { // 将childNodes转为静态数组,避免动态列表导致的遍历跳过问题 foreach (iterator_to_array($section->childNodes) as $childNode) { $nodeValue = trim($childNode->nodeValue); if ($nodeValue === '') { continue; } $count = $count + 1; $key = (string) $keyPattern.'Text'.$count; $vueInterpolation = ' {{ $t("'.$key.'") }} '; // 修复$t()的闭合括号缺失问题 $newNode = $dom->createElement($childNode->nodeName, $vueInterpolation ); $childNode->parentNode->replaceChild($newNode, $childNode); } }
说明
iterator_to_array()将动态DOMNodeList转为静态数组,遍历数组时,即使DOM结构变化,数组内的节点引用不会改变,确保所有符合条件的节点都能被处理。- 补全了原代码中
$t()的闭合括号,避免Vue语法错误。
内容的提问来源于stack exchange,提问作者gabogabans
相关产品推荐
相关产品推荐

