我当前的项目涉及根据提供的选择器从元素及其所有后代收集文本内容.
例如,当提供选择器#content并针对此HTML运行时:
<div id="content"> <p>This is some text.</p> <script type="text/javascript"> var test = true; </script> <p>This is some more text.</p> </div>
我的脚本将返回(经过一些小空格清理):
This is some text. var test = true; This is some more text.
但是,我需要忽略< script>中出现的文本节点.元素.
这是我当前代码的摘录(从技术上讲,它基于一个或多个提供的选择器进行匹配):
// get text content of all matching elements for (x = 0; x < selectors.length; x++) { // 'selectors' is an array of CSS selectors from which to gather text content matches = Sizzle(selectors[x],document); for (y = 0; y < matches.length; y++) { match = matches[y]; if (match.innerText) { // IE content += match.innerText + ' '; } else if (match.textContent) { // other browsers content += match.textContent + ' '; } } }
它有点过于简单了,因为它只返回与提供的选择器匹配的元素(及其后代)中的所有文本节点.我正在寻找的解决方案将返回所有文本节点,除了那些属于< script>的文本节点.元素.它不需要特别高性能,但我确实需要它最终是跨浏览器兼容的.
我假设我需要以某种方式循环遍历与选择器匹配的元素的所有子元素,并累积除< script>内的所有文本节点以外的所有文本节点.要素;一旦它已经被卷入从所有文本节点累积的字符串中,它就没有任何方法可以识别它.
我不能使用jQuery(出于性能/带宽的原因),虽然您可能已经注意到我确实使用了它的Sizzle选择器引擎,因此jQuery的选择器逻辑可用.
在此先感谢您的帮助!
解决方法
function getTextContentExceptScript(element) { var text= []; for (var i= 0,n= element.childNodes.length; i<n; i++) { var child= element.childNodes[i]; if (child.nodeType===1 && child.tagName.toLowerCase()!=='script') text.push(getTextContentExceptScript(child)); else if (child.nodeType===3) text.push(child.data); } return text.join(''); }
或者,如果您被允许更改DOM以删除< script>元素(通常不会有明显的副作用),更快:
var scripts= element.getElementsByTagName('script'); while (scripts.length!==0) scripts[0].parentNode.removeChild(scripts[0]); return 'textContent' in element? element.textContent : element.innerText;