PHP中使用DOMDocument遍历DOM,如何为子节点添加同级等量缩进?
解决PHP DOM遍历并按层级添加缩进的问题
这问题我之前处理过类似的,核心思路是递归遍历DOM节点,跟踪当前层级深度,根据深度给子元素的文本内容添加对应数量的 缩进,确保同级元素的缩进量一致。下面是完整的实现方案:
完整代码示例
<?php // 示例HTML内容 $html = '<div>Parent <div>child</div> <div>child <div>subchild</div> <div>subchild <div>grandsubchild</div> <div>grandsubchild</div> </div> </div> <div>child</div> </div>'; // 初始化DOMDocument并加载HTML(忽略格式错误) $dom = new DOMDocument(); libxml_use_internal_errors(true); // 禁用XML错误报告 $dom->loadHTML($html); libxml_clear_errors(); /** * 递归遍历DOM并添加层级缩进 * @param DOMNode $node 当前遍历的节点 * @param int $depth 当前层级深度(根节点为0) */ function traverseAndIndent(DOMNode $node, int $depth = 0) { // 只处理元素节点(跳过文本、注释等非元素节点) if ($node->nodeType !== XML_ELEMENT_NODE) { return; } // 遍历当前节点的所有子节点 foreach ($node->childNodes as $child) { if ($child->nodeType === XML_ELEMENT_NODE) { // 根据当前层级计算缩进:子元素的缩进是当前深度+1个 $indent = str_repeat(' ', $depth + 1); // 处理子元素的文本节点(假设文本是子元素的第一个直接子节点) if ($child->firstChild && $child->firstChild->nodeType === XML_TEXT_NODE) { // 去除原文本的多余空白,再添加缩进 $cleanText = trim($child->firstChild->nodeValue); $child->firstChild->nodeValue = $indent . $cleanText; } // 递归遍历子元素,层级深度+1 traverseAndIndent($child, $depth + 1); } } } // 从根节点开始遍历处理 traverseAndIndent($dom->documentElement); // 输出处理后的HTML echo $dom->saveHTML(); ?>
关键细节说明
- 递归遍历与层级跟踪:通过
$depth参数记录当前节点的层级,根节点(如最外层<div>)深度为0,子元素深度+1,这样同级元素的缩进量完全一致。 - 节点类型过滤:只处理
XML_ELEMENT_NODE类型的节点,避免误处理文本、注释、CDATA等非元素节点,保证逻辑精准。 - 文本节点处理:找到子元素的第一个文本节点,先去除原文本的多余空白(避免原格式的空格干扰),再添加对应数量的
缩进。如果你的DOM结构中元素文本不是第一个子节点,可调整为遍历所有子节点找文本节点的逻辑。 - HTML兼容性:启用
libxml_use_internal_errors(true)避免因HTML格式不规范(如未闭合标签)导致的加载错误,适配大多数实际场景。
内容的提问来源于stack exchange,提问作者Shehny Khan
相关产品推荐
相关产品推荐

