gpt4 book ai didi

javascript - HTML 标签内的高级 JavaScript RegExp 替换

转载 作者:行者123 更新时间:2023-11-28 20:42:36 24 4
gpt4 key购买 nike

我的 JavaScript 代码运行得很好,例如:

var rgx = /MyName/g;
var curInnerHTML = document.body.innerHTML;
curInnerHTML = curInnerHTML.replace(rgx, "<span><span class='myName'>MyNameReplace</span></span>");

问题是它与正则表达式匹配,即使在它包含在 HTML 属性和其他内容中的情况下也是如此。如何修改正则表达式,使其在 HTML 内容中找到它?例如,在这个字符串中

    <div class="someclass" title="MyName">
MyName
</div>

目前的结果如下(注意标题属性的变化):

        <div class="someclass" title="<span><span class='myName'>MyNameReplace</span</span>">
<span><span class='myName'>
MyNameReplace</span></span>
</div>

但我需要它(保持标题属性不变):

    <div class="someclass" title="MyName">
<span><span class='myName'>MyNameReplace</span></span>
</div>

最佳答案

你最好的选择,而且比听起来容易得多,不是尝试使用正则表达式来解析 HTML,而是利用 DOM 已经具有的事实并递归地处理文本节点。

这是即兴的:

// We use this div's `innerHTML` to parse the markup of each replacment
const div = document.createElement('div');

// This is the recursive-descent function that processes all text nodes
// within the element you give it and its descendants
function doReplacement(node, rex, text) {
// What kind of node did we get?
switch (node.nodeType) {
case Node.ELEMENT_NODE:
// Probably best to leave `script` elements alone.
// You'll probably find you want to add to this list
// (`object`, `applet`, `style`, ...)
if (node.nodeName.toUpperCase() !== "SCRIPT") {
// It's an element we want to process, start with its
// *last* child and work forward, since part of what
// we're doing inserts into the DOM.
let sibling;
for (const child = node.lastChild; child; child = sibling) {
// Before we change this node, grab a reference to the
// one that precedes it
sibling = child.previousSibling;

// Recurse
doReplacement(child, rex, text);
}
}
break;
case Node.TEXT_NODE:
// A text node -- let's do our replacements!
// The first two deal with the fact that the text node
// may have less-than symbols or ampersands in it.
// The third, of course, does your replacement.
div.innerHTML = node.nodeValue
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(rex, text);

// Now, the `div` has real live DOM elements for the replacement.
// Insert them in front of this text node...
insertChildrenBefore(div, node);
// ...and remove the text node.
node.parentNode.removeChild(node);
break;
}
}

// This function just inserts all of the children of the given container
// in front of the given reference node.
function insertChildrenBefore(container, refNode) {
let sibling;
const parent = refNode.parentNode;
for (const child = container.firstChild; child; child = sibling) {
sibling = child.nextSibling;
parent.insertBefore(child, refNode);
}
}

你可以这样称呼:

doReplacement(
document.body,
/MyName/g,
"<span><span class='myName'>MyNameReplace</span></span>"
);

实例:

// We use this div's `innerHTML` to parse the markup of each replacment
const div = document.createElement('div');

// This is the recursive-descent function that processes all text nodes
// within the element you give it and its descendants
function doReplacement(node, rex, text) {
// What kind of node did we get?
switch (node.nodeType) {
case Node.ELEMENT_NODE:
// Probably best to leave `script` elements alone.
// You'll probably find you want to add to this list
// (`object`, `applet`, `style`, ...)
if (node.nodeName.toUpperCase() !== "SCRIPT") {
// It's an element we want to process, start with its
// *last* child and work forward, since part of what
// we're doing inserts into the DOM.
let sibling;
for (let child = node.lastChild; child; child = sibling) {
// Before we change this node, grab a reference to the
// one that precedes it
sibling = child.previousSibling;

// Recurse
doReplacement(child, rex, text);
}
}
break;
case Node.TEXT_NODE:
// A text node -- let's do our replacements!
// The first two deal with the fact that the text node
// may have less-than symbols or ampersands in it.
// The third, of course, does your replacement.
div.innerHTML = node.nodeValue
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(rex, text);

// Now, the `div` has real live DOM elements for the replacement.
// Insert them in front of this text node...
insertChildrenBefore(div, node);
// ...and remove the text node.
node.parentNode.removeChild(node);
break;
}
}

// This function just inserts all of the children of the given container
// in front of the given reference node.
function insertChildrenBefore(container, refNode) {
let sibling;
const parent = refNode.parentNode;
for (let child = container.firstChild; child; child = sibling) {
sibling = child.nextSibling;
parent.insertBefore(child, refNode);
}
}

setTimeout(() => {
doReplacement(
document.body,
/MyName/g,
"<span><span class='myName'>MyNameReplace</span></span>"
);
}, 800);
<p>MyName</p>
<p>This is MyName in a sentence.</p>
<p>This is <strong>MyName nested</strong></p>
<p>How 'bout <strong><em>making MyName nested more deeply</em></strong></p>
<p>This is MyName in an element with &lt; and &amp; in it.</p>

关于javascript - HTML 标签内的高级 JavaScript RegExp 替换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14104992/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com