如何使用Javascript在HTML字符串的文本部分中查找子字符串?

时间:2015-11-03 21:07:33

标签: javascript html string

更新:我不再特别需要这个问题的答案 - 我能够以完全不同的方式解决(更大)问题(请参阅我的评论)。但是,我偶尔会检查,如果有可行的答案,我会接受它。 (可能需要一到三周的时间,因为我只是偶尔来这里。)

我有一个字符串。它可能包含也可能没有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;在上面的每个字符串中:

  • 搜索第一个将返回13(从0开始),
  • 搜索第二个将跳过字符串中的开始span标记,并为单词span中的字符串spanned返回35
  • 搜索第三个将跳过空span标记和两个嵌套span标记的开头,并返回91
  • 搜索第四个将跳过嵌套的span标记并打开第二个span标记,并返回100

我不想删除任何HTML标记,我只是不想将它们包含在搜索中。

我知道尝试使用正则表达式几乎肯定a bad idea,甚至可能是因为我的代码会遇到简单的字符串,所以请不要提示它。

我猜我需要使用HTML解析器(我之前从未做过的事情)。是否有一个我可以访问每个节点的原始解析字符串(或至少它们的长度)?

可能有比这更简单的解决方案吗?

我确实搜索过,之前没有人能找到这个问题,所以如果有人知道我错过了什么,我会为错误的搜索技巧道歉。

4 个答案:

答案 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);
}

JSFiddle.

答案 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);

最后,您可以将indexOfTextStringindexOfSubStringWithinTextString加在一起:

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;