当 HTML 可能有子元素时,如何 Javascript 用新文本替换 HTML 文本

How to Javascript to replace HTML text with new text when the HTML may have children elements

我正在尝试使用 JavaScript 搜索所有 p 元素以查找正则表达式,但我要查找的文本可能部分存在于属性元素中或包含在其中,也可能不存在一个跨度。最终,我计划修复 HTML 代码中应用于 Word 项目符号项的交叉引用,方法是添加一个属性元素,该元素引用我之前插入的 html id JavaScript.

我的总体项目是创建一个 Word 文档,我使用“另存为”功能让 Word 创建一个过滤后的 HTML 文件。我最终使用 JavaScript 来插入 ID 和标签,这样我就可以利用 CSS 文件来标准化我所有 HTML 文件的格式。因此,我对初始 HTML 代码的控制有限。

到目前为止,我已经能够创建遍历所有 p 元素的循环。在循环中,我能够为“/Step (\d+)/”的 innerText 上的正则表达式执行条件语句,因为我希望文本看起来类似于第 1 步、第 12 步或任何其他数字。下面的代码似乎成功进入了 if 语句。我 运行 遇到了 innerHTML 部分的替换函数的麻烦,因为 innerText 匹配表达式,但 innerHTML 包含阻止我正在寻找的最终结果的元素.我希望能够一般地解释任何其他元素,例如粗体、斜体、a 等。为此,我尝试使用多个 if 语句来替换各种潜在的 HTML 条件。

我试图通过将粗体应用于文本来弄清楚这项技能,以确保我了解如何完成此特定功能。到目前为止,我所做的所有搜索都有助于使正则表达式匹配 innerText,但我找不到方法或忽略无关的 html 代码。我当时在想,可以用新的 HTML 代码存储替换的 innerText,然后将其设为新的 innerHTML,但我想维护的 p 元素中可能有其他格式。

我采用的方法是为内部 HTML 替换使用第二个正则表达式,贪婪搜索似乎我会捕获错误结果,即使正则表达式正在捕获它。

HTML

<p id="FirstPara" class=firstpara>This is a header</p>
<p class=firstpara>This is a reference to Step <span lang=HE>&#8206; </span><b>1</b>.</p>
<p class=firstpara>This is a reference to Step <span lang=HE>&#8206;</span>2.</p>
<p class=firstpara>This is a reference to Step <span lang=HE>&#8206;</span>1 and Step <span lang=HE>&#8206;</span>2.</p>

JavaScript函数

function findTheText() {
    regExp1 = /Step (\d)/g;
    for (var i = 0; i < document.getElementsByTagName('p').length; i++) {
                alert(i+" - "+j+" - "+document.getElementsByTagName('p')[i].innerHTML+" - "+results[j]);
        var results = document.getElementsByTagName('p')[i].innerText.match(regExp1);
        if (results !== null) {
            for (var j = 0; j < results.length; j++) {
                var replace = results[j].replace(/Step\s/,"");
                var regExp2 = new RegExp('Step\s'+replace,"i");
                var regExp3 = new RegExp('Step\s.*>'+replace,"i");
                var regExp4 = new RegExp('Step\s.*>.*>'+replace,"i");
                var results2 = document.getElementsByTagName('p')[i].innerText.match(regExp2);
                var results3 = document.getElementsByTagName('p')[i].innerText.match(regExp3);
                var results4 = document.getElementsByTagName('p')[i].innerText.match(regExp4);
                    if (results2 !== null) {
                        document.getElementsByTagName('p')[i].innerHTML.replace(regExp2, "<b>"+results[j]+"</b>");
                    } else if (results3 !== null) {
                        document.getElementsByTagName('p')[i].innerHTML.replace(regExp3, "<b>"+results[j]+"</b>");
                    } else if (results4 !== null) {
                        document.getElementsByTagName('p')[i].innerHTML.replace(regExp4, "<b>"+results[j]+"</b>");
                    }
            }
        }
    }

}

截至目前,代码将找到我想要的文本,但由于正则表达式匹配我正在寻找的字符串,但内部 HTML 不匹配我没有实现粗体(或最终属性)在文本上。

预期HTML输出

<p class=firstpara>This is a reference to <b>Step 1</b>.</p>
<p class=firstpara>This is a reference to <b>Step 2</b>.</p>
<p class=firstpara>This is a reference to <b>Step 1</b> and <b>Step 2</b>.</p>

我不太确定这是您期望的结果,但这段代码可能有效。您甚至可以更新它以使用箭头函数和模板文字。

function findTheText() {
  let regExp1 = /Step (\d)/g;
  let paragraphs = document.getElementsByTagName('p');

  for (var i = 0; i < paragraphs.length; i++) {
    let spans = Array.from(paragraphs[i].getElementsByTagName('span'));
    spans.forEach(function(child) {
      paragraphs[i].removeChild(child);
    })

    if (paragraphs[i].innerHTML.match(regExp1)) {
      let replace = paragraphs[i].innerHTML.match(regExp1);
      replace.forEach(function(match) {
        paragraphs[i].innerHTML = paragraphs[i].innerHTML.replace(match, "<b>" + match + "</b>");
      })
    };
  }
}

findTheText()
<p id="FirstPara" class=firstpara>This is a header</p>
<p class=firstpara>This is a reference to Step <span lang=HE>&#8206; </span>1.</p>
<p class=firstpara>This is a reference to Step <span lang=HE>&#8206;</span>2.</p>
<p class=firstpara>This is a reference to Step <span lang=HE>&#8206;</span>1 and Step <span lang=HE>&#8206;</span>2.</p>

您可以删除所有子 spans,然后检查 textContent 以忽略其余标记(如 <b>s),捕获步骤数字并替换为被 <b></b>:

包围

document.querySelectorAll('p').forEach((p) => {
  p.querySelectorAll('span').forEach(span => span.remove());
  p.innerHTML = p.textContent.replace(/Step +(\d+)/g, '<b>Step </b>');
});
<p id="FirstPara" class=firstpara>This is a header</p>
<p class=firstpara>This is a reference to Step <span lang=HE>&#8206; </span><b>1</b>.</p>
<p class=firstpara>This is a reference to Step <span lang=HE>&#8206;</span>2.</p>
<p class=firstpara>This is a reference to Step <span lang=HE>&#8206;</span>1 and Step <span lang=HE>&#8206;</span>2.</p>

仅删除 langHEspan

document.querySelectorAll('p').forEach((p) => {
  p.querySelectorAll('span[lang="HE"]').forEach(span => span.remove());
  p.innerHTML = p.textContent.replace(/Step +(\d+)/g, '<b>Step </b>');
});
<p class=firstpara>This is a <span>reference</span> to Step <span lang=HE>&#8206; </span><b>1</b>.</p>