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

时间:2019-01-13 02:57:57

标签: javascript html regexp-replace

我正在尝试使用JavaScript搜索所有p元素以查找正则表达式,但是我正在寻找的文本可能会或可能不会部分存在于attribute元素中或包含在span内。最终,我计划通过添加属性元素和对我以前用JavaScript插入的html id的引用来修复Word中应用于Word项目符号项的HTML代码中的交叉引用。

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

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

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

使用我要使用的第二个正则表达式替换innerHTML替换的方法,贪婪的搜索似乎即使我捕获了正则表达式也会捕获错误的结果。

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>");
                    }
            }
        }
    }

}

到目前为止,代码将找到我想要的文本,但是由于正则表达式与我要查找的字符串匹配,但是innerHTML并不能实现文本的粗体(或最终属性)。

预期的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>

2 个答案:

答案 0 :(得分:1)

您可以删除所有子span,然后检查textContent以忽略其余的标记(例如<b>),捕获步骤数字并用<b></b>

document.querySelectorAll('p').forEach((p) => {
  p.querySelectorAll('span').forEach(span => span.remove());
  p.innerHTML = p.textContent.replace(/Step +(\d+)/g, '<b>Step $1</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>

要仅删除spanlangHE的{​​{1}}:

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

答案 1 :(得分:0)

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

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>