我正在寻找一种方法来使用javascript将带有HTML的句子拆分为单词,并保留带有文本内容的内嵌HTML标记。标点符号可以被视为它最接近的单词的一部分。我想使用正则表达式,可能preg_split()
来分割句子。以下是一个例子:
A word, <a href='#' title=''>words within tags should remain intact</a>, so here's
<b>even more</b> <u>words</u>
最好,我想最终得到以下结论:
[0] => A
[1] => word,
[2] => <a href='#' title=''>words within tags should remain intact</a>,
[3] => so
[4] => here's
[5] => <b>even more</b>
[6] => <u>words</u>
我知道有关使用Regex解析HTML的讨论(我喜欢阅读Bobince' answer :- P),但我需要拆分句子的单词而不会损坏带有属性的html标签。我不知道如何使用JS以与Regex不同的方式来实现这一点。当然,如果有其他选择,我会非常乐意调整它们,以达到类似的效果。 : - )
修改 我在Stackoverflow上搜索了类似的问题,但这些问题并没有为我打勾。稍微透视一下:
答案 0 :(得分:2)
这是可能的,但使用纯正则表达式解决方案会有一些缺点。最容易调用的是嵌套HTML。我即将展示的解决方案使用一些反向引用来试图解决这个问题,但是如果你得到一些复杂的嵌套HTML,它可能会以奇怪的方式开始失败。
/(?:<(\w+)[^>]*>(?:[\w+]+(?:(?!<).*?)<\/\1>?)[^\s\w]?|[^\s]+)/g
正则表达式使用反向引用和负面外观来完成工作。您可以根据需要删除后退参考。后引用有助于支持嵌套标记。
JSFiddler Example - 检查控制台输出中的示例。
这是JS Fiddler的输出(我稍微格式化了输出)
[
"A",
"word,",
"<a href='#' title=''>words within tags should remain intact</a>,",
"so",
"here's",
"<b>even more</b>",
"<u>words</u>"
]
根据您的使用情况,您需要对其进行修改才能使用。我考虑过任何不是空格的词,但你可能有不同的标准。
此方法的一个不利之处是,如果起始HTML标记位于单词的末尾,则无法正确拾取。即。 test<span>something else</span>
。
答案 1 :(得分:1)
您可以使用以下代码段:
function splitIntoWords(div) {
function removeEmptyStrings(k) {
return k !== '';
}
var rWordBoundary = /[\s\n\t]+/; // Includes space, newline, tab
var output = [];
for (var i = 0; i < div.childNodes.length; ++i) { // Iterate through all nodes
var node = div.childNodes[i];
if (node.nodeType === Node.TEXT_NODE) { // The child is a text node
var words = node.nodeValue.split(rWordBoundary).filter(removeEmptyStrings);
if (words.length) {
output.push.apply(output, words);
}
} else if (node.nodeType === Node.COMMENT_NODE) {
// What to do here? You can do what you want
} else {
output.push(node.outerHTML);
}
}
return output;
}
window.onload = function() {
var div = document.querySelector("div");
document.querySelector("pre").innerText = 'Output: ' + JSON.stringify(splitIntoWords(div));
}
&#13;
<!-- Note you have to surround your html with a div element -->
<div>A word, <a href='#' title=''>words within tags should remain intact</a>, so here's
<b>even more</b> <u>words</u>
</div>
<pre></pre>
&#13;
它遍历所有子节点,获取文本节点并将它们分成单词(您可以安全地执行此操作,因为文本节点不能包含子节点)。
这可以解决大多数问题。有了这个,text<span>Test</span>
之类的HTML将会出现["text", "<span>Test</span>"]
,与上面的答案不同。
这可能会导致<span>There are</span>: 4 words
失败,导致["<span>There are</span>", ":" /* Extra colon */, "4", "words"]
(它应该这样做,但不确定是否合适)。
我认为嵌套元素非常安全。