【问题标题】:How to Javascript to replace HTML text with new text when the HTML may have children elements当 HTML 可能有子元素时,如何使用 Javascript 用新文本替换 HTML 文本
【发布时间】:2019-06-07 12:15:18
【问题描述】:

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

我的总体项目是创建一个 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 元素中可能还有其他格式。

通过我使用第二个正则表达式进行 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>

【问题讨论】:

  • 我遇到的问题是Step 和数字之间的span 包含一个字符,所以最初的/Step (\d)/ 模式失败:jsfiddle.net/j8yxwa2p 也许首先删除所有@ 987654328@标签?
  • 我正在考虑的一个选项是通过 VBA 脚本运行 html 代码以尝试清除该文本,但我想我会遇到同样的问题,因为这些只是原始html代码中可能包含什么。我将对这些额外的 HTML 项目进行一些控制,因为我计划在创建 Word 文档时使用一些标准化,但我预计可能会有其他情况。我在问题中添加了一个示例,除了整个 Step # 也应该是粗体的跨度之外,只有数字是粗体的。这就是我对“if”正则表达式的希望。
  • span里面可以有嵌套标签吗?如果没有,那么在他们周围匹配Steps 并根据需要替换并不难
  • 我不相信我应该在跨度内看到额外的嵌套标签。我相信 Word 生成了这些,因为我在生成 HTML 之前在 Word 文档中创建了交叉引用。我知道必须在为我的情况生成之前添加这些交叉引用。我真正期待的唯一其他标签是我在示例中添加的粗体。

标签: javascript html regexp-replace


【解决方案1】:

您可以删除所有子 spans,然后检查 textContent 以忽略其余标记(如 &lt;b&gt;s),捕获步数并替换为 &lt;b&gt; 和 @987654325 包围的数字@:

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>

仅删除带有langHEspans:

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>');
});
&lt;p class=firstpara&gt;This is a &lt;span&gt;reference&lt;/span&gt; to Step &lt;span lang=HE&gt;&amp;#8206; &lt;/span&gt;&lt;b&gt;1&lt;/b&gt;.&lt;/p&gt;

【讨论】:

  • 这绝对达到了HTML的sn-p的目标。我正在尝试代码并注意到所有 span 元素都被取出,所以我尝试了一些条件语句来只考虑带有步骤号的 innerText 段落。我无法解决的情况是,如果该段落是:

    This is a reference to Step 1.

    在这种情况下,文本被删除。你知道解决这个问题的任何方法吗?我一直没有成功地回到我的原始代码中尝试多个正则表达式。
  • 如果您可以指望要删除的不良跨度始终具有HElang 属性,请专门删除它们,仅此而已,请参阅编辑
【解决方案2】:

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

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>

【讨论】:

  • 请注意,1 也可能在标签内。 &lt;/span&gt;&lt;b&gt;1&lt;/b&gt;.&lt;/p&gt;
  • 你是对的,感谢您的提醒。此外,当我看到您提出的解决方案时,我意识到矿井不必要地长了。谢谢你:)
猜你喜欢
  • 2011-10-11
  • 2016-02-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-12
相关资源
最近更新 更多