You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS递归DOM处理函数为何未处理段落标签?需保留li提取文本

问题:递归函数未处理段落标签,p及code标签未被替换为纯文本的原因

需求说明

仅保留HTML中的li标签,其余标签仅保留文本内容。

现有JS代码

let html = `
<ol>
<li><a href="#"><code>foo</code> link text</a>;</li>
<li><a href="#"><code>bar</code> link text</a>;</li>
</ol>
<p>Paragraph text <code>baz</code> and <code>biz</code> text.</p>
<p>Paragraph text.</p>
`;

html = `<body>${html}</body>`;

let parsed = new DOMParser().parseFromString( html, 'text/html' );

function testFn( node  ) {

    node.childNodes.forEach( function( e ) {

        testFn( e );

        if ( e.nodeType !== Node.ELEMENT_NODE ) return;

        if ( e.nodeName.toLowerCase() !== 'li' ) {

            e.replaceWith( ...e.childNodes );
        }
    });
}

testFn( parsed.body );

console.log( parsed.body.innerHTML );

运行结果

<li>foo link text;</li>
<li>bar link text;</li>

<p>Paragraph text <code>baz</code> and <code>biz</code> text.</p>
<p>Paragraph text.</p>

预期结果

<li>foo link text;</li>
<li>bar link text;</li>

Paragraph text baz and biz text.
Paragraph text.

问题原因分析

1. HTML转义导致DOM解析异常(代码示例中的关键错误)

你的代码里用&lt;和&gt;转义了所有HTML标签,包括包裹内容的<body>。DOMParser解析这类转义字符串时,会把它们当作纯文本内容而非实际的DOM元素。这就导致<p>和<code>都只是文本字符串,不会被识别为元素节点,自然无法触发替换逻辑。

要正确解析成DOM结构,需使用未转义的标签(直接写<body>而非&lt;body&gt;)。

2. 递归遍历的逻辑缺陷(核心问题)

假设修正了转义问题,原代码仍可能出现<p>未被替换的情况,原因是:

  • node.childNodes是动态更新的NodeList,当你替换某个节点(比如把<ol>换成<li>),会实时改变父节点的子节点结构,导致forEach遍历跳过后续部分节点。
  • 原函数的处理顺序是先递归处理子节点,再判断当前节点是否替换。但对于<p>这类节点,当完成子节点处理后,动态变化的NodeList可能导致替换逻辑未被正确触发。

修正后的代码

改用反向遍历(避免动态NodeList的影响),确保所有非li元素都被正确替换:

let html = `
<ol>
<li><a href="#"><code>foo</code> link text</a>;</li>
<li><a href="#"><code>bar</code> link text</a>;</li>
</ol>
<p>Paragraph text <code>baz</code> and <code>biz</code> text.</p>
<p>Paragraph text.</p>
`;

html = `<body>${html}</body>`;

let parsed = new DOMParser().parseFromString(html, 'text/html');

function testFn(node) {
    // 反向遍历,避免动态NodeList导致的节点丢失
    for (let i = node.childNodes.length - 1; i >= 0; i--) {
        const e = node.childNodes[i];
        testFn(e);
        if (e.nodeType !== Node.ELEMENT_NODE) continue;
        if (e.nodeName.toLowerCase() !== 'li') {
            e.replaceWith(...e.childNodes);
        }
    }
}

testFn(parsed.body);

console.log(parsed.body.innerHTML);

内容的提问来源于stack exchange,提问作者Pavel Rozhdestvenskiy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 18:50:26