我想在HTML文档中找到与RegEx匹配的所有TEXT或HREF,并用标记包装它们(例如将纯文本转换为链接)。
请考虑以下HTML:
<body>
<!-- test1 <div>test2 <a href="test3">test4</a></div> -->
test5
<a href="test6">notest</a>
<div>
test8
<p>
test9 notest test10
<a href="notest">test12</a>
<input type="text" name="test13">test14</input>
</p>
test15
</div>
</body>
那么这将是我要求的替代品:
<body>
<!-- test1 <div>test2 <a href="test3">test4</a></div> -->
<div class="wrapped">test5</div>
<div class="wrapped"><a href="test6">notest</a></div>
<div>
<div class="wrapped">test8</div>
<p>
<div class="wrapped">test9</div> notest
<div class="wrapped">test10</div>
<div class="wrapped"><a href="notest">test12</a></div>
<input type="text" name="test13">test14</input>
</p>
<div class="wrapped">test15</div>
</div>
</body>
请注意,测试5, 6, 8, 9, 10, 12, 15
被包裹了。
插入输入框或任何其他未显示的特殊HTML标记(例如<script>
<doctype>
等)是不可接受的。
我之前正在使用堆栈原则:
e = stack.pop()
。e
的所有子元素推入堆栈,除了链接(<a>
节点)和class="wrapped"
的元素。e.children
或文本和包装的所有剩余href
类型链接。e.children
中包装所有最里面的匹配。JavaScript只需要在Firefox 8上运行。
我想在没有树遍历的情况下完成包装,线性将是最佳的
你为什么不想要任何树遍历?我认为你当前的算法和它一样好。
问题是DOM没有提供任何复杂的方法来获取所有文本节点。
我没有进行任何性能测试,但是这个速度可能大致相同:
nodes := getElementsByTagName('*')
excludes := document.querySelectorAll('a, a *, .wrapped, .wrapped *, script, style, input, textarea [, ...]')
(querySelectorAll
表现相当不错)targets := nodes - excludes
(不确定这里的表现)targets
迭代孩子
包装每个textNode<a>
元素你很幸运!我不久前写了这样的东西。
它可能需要一些修改才能使它与正则表达式一起使用,但这不应该太难。该代码已在IE7,8,9,Chrome和Firefox中进行了测试
/*global window document addEvent*/
function textContent(node) {
if (typeof node.textContent !== "undefined") {
return node.textContent;
} else {
return node.nodeValue; // IE
}
}
function setTextContent(node, new_value) {
if (typeof node.textContent !== "undefined") {
node.textContent = new_value;
} else {
node.nodeValue = new_value; // IE
}
}
function replace_stuff(context_element) {
var i = 0, node, pos, before, after, div;
if (1 === context_element.nodeType) {
for (; i < context_element.childNodes.length; i += 1) {
replace_em(context_element.childNodes[i]);
}
} else if (3 === context_element.nodeType) {
node = context_element;
pos = textContent(node).indexOf("YOURSTRING"); // replace with regex if you so desire
while (-1 !== pos) {
before = textContent(node).substring(0, pos);
after = textContent(node).substring(pos + 10, textContent(node).length); // 10 is the lenth of YOURSTRING
context_element.parentNode.insertBefore(document.createTextNode(before), node);
div = document.createElement("div");
div.appendChild(document.createTextNode("YOURSTRING")); // reinsert original content
context_element.parentNode.insertBefore(div, node);
setTextContent(node, after);
pos = textContent(node).indexOf("YOURSTRING"); // find next occurance
}
}
}
addEvent(window, "load", function () { // you may need to change this line
replace_stuff(document.getElementById("main"));
});
基本上它检查节点的textContent
是否为YOURSTRING,将文本分成两个节点:YOURSTRING之前的文本和之后的文本。然后它将YOURSTRING包装在div中并将其插入到其他两个节点之间。