更新:我不再特别需要这个问题的答案 - 我能够以完全不同的方式解决(更大)问题(请参阅我的评论)。但是,我偶尔会检查,如果有可行的答案,我会接受它。 (可能需要一到三周的时间,因为我只是偶尔来这里。)
我有一个字符串。它可能包含也可能没有HTML标记。所以,它可能是:
'This is my unspanned string'
或者可能是:
'<span class="someclass">This is my spanned string</span>'
或:
'<span class="no-text"></span><span class="some-class"><span class="other-class">This is my spanned string</span></span>'
或:
'<span class="no-text"><span class="silly-example"></span></span><span class="some-class">This is my spanned string</span>'
我想找到一个子字符串的索引,但只在字符串的一部分中,如果字符串被转换为DOM元素,则是(a)TEXT节点。在示例中,仅在字符串中具有纯文本This is my string
的部分。
但是,我需要整个字符串中子字符串的位置,而不仅仅是纯文本部分。
所以,如果我正在寻找&#34; span&#34;在上面的每个字符串中:
span
标记,并为单词span
中的字符串spanned
返回35 span
标记和两个嵌套span
标记的开头,并返回91 span
标记并打开第二个span
标记,并返回100 我不想删除任何HTML标记,我只是不想将它们包含在搜索中。
我知道尝试使用正则表达式几乎肯定a bad idea,甚至可能是因为我的代码会遇到简单的字符串,所以请不要提示它。
我猜我需要使用HTML解析器(我之前从未做过的事情)。是否有一个我可以访问每个节点的原始解析字符串(或至少它们的长度)?
可能有比这更简单的解决方案吗?
我确实搜索过,之前没有人能找到这个问题,所以如果有人知道我错过了什么,我会为错误的搜索技巧道歉。
答案 0 :(得分:0)
搜索可以通过char遍历字符串char。如果在标记内,跳过标记,仅在标记之外搜索字符串并记住部分匹配,以防文本部分匹配然后用另一个标记中断,继续在标记外搜索。
答案 1 :(得分:0)
您可以使用浏览器自己的HTML解析器和XPath引擎仅在文本节点内搜索并执行您需要的任何处理。
这是一个部分解决方案:
var haystack = ' <span class="no-text"></span><span class="some-class"><span class="other-class">This is my spanned string</span></span>';
var needle = 'span';
var elt = document.createElement('elt');
elt.innerHTML = haystack;
var iter = document.evaluate('.//text()[contains(., "' + needle + '")]', elt).iterateNext();
if (iter) {
var position = iter.textContent.indexOf(needle);
var range = document.createRange();
range.setStart(iter, position);
range.setEnd(iter, position + needle.length);
// At this point, range points at the first occurence of `needle`
// in `haystack`. You can now delete it, replace it with something
// else, and so on, and after that, set your original string to the
// innerHTML of the document fragment representing the range.
console.log(range);
}
答案 2 :(得分:0)
这是我提出的一个小功能:
function customSearch(haysack,needle){
var start = 0;
var a = haysack.indexOf(needle,start);
var b = haysack.indexOf('<',start);
while(b < a && b != -1){
start = haysack.indexOf('>',b) + 1;
a = haysack.indexOf(needle,start);
b = haysack.indexOf('<',start);
}
return a;
}
它会根据您的示例返回您期望的结果。这是一个JSFiddle,其中的结果记录在控制台中。
答案 3 :(得分:0)
让我们从你的第三个例子开始:
var desiredSubString = 'span';
var entireString = '<span class="no-text"></span><span class="some-class"><span class="other-class">This is my spanned string</span></span>';
从上面的entireString
中移除所有HTML元素,以建立textString
:
var textString = entireString.replace(/(data-([^"]+"[^"]+")/ig,"");
textString = textString.replace(/(<([^>]+)>)/ig,"");
然后,您可以在textString
中找到entireString
的开头索引:
var indexOfTextString = entireString.indexOf(textString);
然后你可以在textString
中找到你要查找的子字符串开头的索引:
var indexOfSubStringWithinTextString = textString.indexOf(desiredSubString);
最后,您可以将indexOfTextString
和indexOfSubStringWithinTextString
加在一起:
var indexOfSubString = indexOfTextString + indexOfSubStringWithinTextString;
全部放在一起:
var entireString = '<span class="no-text"></span><span class="some-class"><span class="other-class">This is my spanned string</span></span>';
var desiredSubString = 'span';
var textString = entireString.replace(/(data-([^"]+"[^"]+")/ig,"");
textString = textString.replace(/(<([^>]+)>)/ig,"");
var indexOfTextString = entireString.indexOf(textString);
var indexOfSubStringWithinTextString = textString.indexOf(desiredSubString);
var indexOfSubString = indexOfTextString + indexOfSubStringWithinTextString;