【问题标题】:How to search and replace all tags in HTML file using Vanilla JavaScript?如何使用 Vanilla JavaScript 搜索和替换 HTML 文件中的所有标签?
【发布时间】:2021-02-09 11:31:01
【问题描述】:

我没有尝试对内容做任何事情(至少现在还没有。)我想做的是搜索特定标签并将它们替换为另一个标签。

我得到了这个 HTML,它用相同的 ID 填充了这些标签(我知道这太可怕了!)

<div dir="rtl" id="book-container">
some text here #1
</div>

<div dir="rtl" id="book-container">
some text here #2
</div>

<div dir="rtl" id="book-container">
some text here #3
</div>

.
.
.

<div dir="rtl" id="book-container">
some text here #49
</div>

<div dir="rtl" id="book-container">
some text here #50
</div>

我正在尝试编写一个函数来搜索每个&lt;div dir="rtl" id="book-container"&gt; 并删除它而不删除内部文本。然后搜索每个&lt;/div&gt; 并将其删除。然后,将整个内容包装在 &lt;p&gt; 标签中。

结果应该是这样的:

<p>
some text here #1

some text here #2

some text here #3

.
.
.

some text here #49

some text here #50
</p>

【问题讨论】:

  • 这是 HTML 的全部内容吗?是否还有其他divs、其他带有dir="rtl" 的元素或其他带有id="book-container" 的元素?
  • 只有带有dir="rtl"的元素。
  • 如果您在内容中有任何&lt;p&gt; 标签未被替换,那么如果您将全部内容包装在&lt;p&gt; 中,则生成的html 将无效。或者您是否希望将替换的内容移出常规流程?下一个问题,如果纯粹出于样式原因 CSS 可以处理它,为什么要这样做?
  • 我在内容中没有任何

    。我不确定你的第二个问题。我只想将内容放在一个

    标签而不是 div 中。我这样做是因为我正在为一本书清理 html。

  • 一切包裹在&lt;div dir="rtl" id="book-container"&gt;节点中还是有其他兄弟节点。例如:&lt;div dir="rtl" id="book-container"&gt;Something&lt;/div&gt;&lt;div&gt;A sibling&lt;/div&gt;&lt;div dir="rtl" id="book-container"&gt;Something Else&lt;/div&gt;

标签: javascript html dom dom-manipulation


【解决方案1】:

这是我解决问题的方法,并附有解释每个步骤的注释。

我抽取了三个元素的样本并将它们包含在body 标签中:

/* Create a paragraph element where the content will be displayed */
const theParagraph = document.createElement("p");
/* Choosing the elements */
const soWrongNodes = document.querySelectorAll("#book-container")
/* For each element, put its content in the paragraph then remove the 
element */
soWrongNodes.forEach(soWrongNode => {
  theParagraph.innerHTML += soWrongNode.innerHTML;
  theParagraph.innerHTML += "<br>";
  soWrongNode.remove();
})
/* Append the paragraph element to the body */
document.body.appendChild(theParagraph);
<body>
  <div dir="rtl" id="book-container">
    some text here #1
  </div>
  <div dir="rtl" id="book-container">
    some text here #2
  </div>
  <div dir="rtl" id="book-container">
    some text here #3
  </div>
</body>

这是fiddle.js,您可以在其中查看结果。

【讨论】:

  • 当然可以。该解决方案也可以满足这一要求。
  • 如果有人正在阅读本文并希望在即将删除的标签中保留任何 html 标签,请使用 innerHTML 而不是 interText。编辑:感谢您的编辑!
  • 你可以跳过这里的第二个循环,只需将内容附加到第一个循环中的新p元素,在循环之前声明新元素。
  • @JonP ,如果你不介意解释为什么我可以跳过第二个循环?
  • @JonP 好点。和 CaptainCustard,希望这个编辑后的代码可以帮助您将其可视化。
【解决方案2】:

replaceWith 可能就是你想要的

//Get the offending nodes
let candidates = document.querySelectorAll("#book-container");
//And iterate them
for(let i = 0; i < candidates.length; i++){
  //Get a node
  let candidate = candidates[i];
  //Create a replacement, could use createTextNode if you don't want to wrap it
  //Or change the element, add styles etc if you want.
  let replacement = document.createElement("p");
  //Set the inner text from the node
  replacement.innerText = candidate.innerText;
  //Replace the node
  candidate.replaceWith(replacement);  
}
<div dir="rtl" id="book-container">
some text here #1
</div>

<div dir="rtl" id="book-container">
some text here #2
</div>

<div dir="rtl" id="book-container">
some text here #3
</div>

<p>Some Other</p>
<p>Content</p>

<div dir="rtl" id="book-container">
some text here #49
</div>

<div dir="rtl" id="book-container">
some text here #50
</div>

您可能还想调查textContenthow it differs from innerText

【讨论】:

  • 这会在每个元素周围放置一个

    ,而不是在整个事物周围放置一个

  • 是否有任何不在&lt;div dir="rtl" id="book-container"&gt; 中的内容将位于文档的同一级别?如果是这样,您是否需要维护文档的流程?例如在我的示例中使用随机的p 标签?
  • 是的,我需要维护文档的流程(如果您的意思是顺序)。不,没有其他任何带有 div 标签或相同 ID 的内容。
【解决方案3】:

更新:

function removeElements() {
  let parent = document.getElementById('book-container').parentElement;
  let elems = Array.from(parent.children);
  let texts = []
  let group = []
  
  let replace = () => {
    if (group.length) {
      let groupElem = document.createElement('p');
      groupElem.innerHTML = group.map(e => e.innerText).join('<br/>')
      group[0].replaceWith(groupElem);
      for (let i = 1; i < group.length; ++i) {
        group[i].remove();
      }
    }
    group = []
  };
  
  for (let elem of elems) {
    if (elem.tagName == 'DIV' && elem.id == 'book-container') { group.push(elem); }
    else { replace(); }
  }
  
  replace();
}

removeElements()
<div dir="rtl" id="book-container">
some text here #1
</div>

<div dir="rtl" id="book-container">
some text here #2
</div>

<div dir="rtl" id="book-container">
some text here #3
</div>

<p>Some Other</p>
<p>Content</p>

<div dir="rtl" id="book-container">
some text here #49
</div>

<div dir="rtl" id="book-container">
some text here #50
</div>

【讨论】:

  • 如果我对它使用remove(),它不会也删除内容吗?
  • 我需要保留内容。使用属性是什么意思?
  • 尝试在 elem 上使用 remove() 时出现错误。有什么解决办法吗?
  • 未捕获的类型错误:elem.remove 不是脚本中 removeElement (script.js:43) 处的函数:53 removeElement @ script.js:43 (anonymous) @ script.js:53
  • 现在出现了!未捕获的类型错误:无法在 script.js:53 处的 removeElement (script.js:44) 处读取未定义的属性“appendChild”
猜你喜欢
  • 1970-01-01
  • 2011-01-06
  • 2017-11-12
  • 2019-03-03
  • 1970-01-01
  • 1970-01-01
  • 2018-09-15
  • 2012-12-17
  • 1970-01-01
相关资源
最近更新 更多