在WebBrowser控件中查找字符串并在忽略大小写的情况下替换它

时间:2014-08-14 14:48:38

标签: vb.net string webbrowser-control

我目前有一个搜索工作,并通过将找到的文本替换为找到的文本来突出显示找到的文本,但是用span标记包装以突出显示。除两个问题外,工作正常。它目前区分大小写,我无法弄清楚如何滚动到第一个找到的实例。如果用户搜索“喷嘴”,他们需要能够找到“喷嘴”。这是我的代码。

Try
    tmrSearch.Stop()
    Try
        If txtSearch.Text.Length <= 3 Then
            If txtSearch.Text <> "" Then
                MessageBox.Show("Please enter longer search terms!")
                txtSearch.Text = String.Empty
            End If
        Else
            Dim searchString As String = txtSearch.Text
            Dim textToSearch As String = wbContent.Document.Body.InnerHtml

            textToSearch = textToSearch.Replace(searchString, "<span style=""background-color:yellow"">" & searchString & "</span>")

            If textToSearch.IndexOf(searchString) <> -1 Then
                wbContent.Document.Body.InnerHtml = textToSearch
            Else
                MessageBox.Show(searchString & " is not located in this text!")
            End If

            txtSearch.Text = String.Empty
        End If
    Catch ex As Exception
        MessageBox.Show("Please enter search terms!")
        logger.WriteLog("Error Message : " & ex.Message)
    End Try
Catch ex As Exception
    logger.WriteLog("frmContent : tmrSearch_Tick() : FAILED")
    logger.WriteLog("Error Message : " & ex.Message)
End Try

我知道.Replace()区分大小写,所以我想我会强制降低textToSearch但是当我把它放回去时,Web浏览器控件中的所有文本都是小写的。这不符合我的需要。这里的任何建议将不胜感激。

3 个答案:

答案 0 :(得分:1)

基本上,您可以尝试拆分小写innertext以查找搜索字符串的存在位置。然后使用拆分中的字符串长度从原始案例副本重建innerText。您需要导入system.text才能使用stringbuilder。

Else
    Dim searchString As String = txtSearch.Text

    Dim textOriginal As String = wbContent.Document.Body.InnerHtml
    Dim textToLower As String = wbContent.Document.Body.InnerHtml.ToLower()

    Dim textPieces() as String = textToLower.Split(New String() {searchString}, StringSplitOptions.RemoveEmptyEntries)

    Dim i as integer = 0
    Dim strNewInnerHtml as New StringBuilder

    For each strPiece as String In textPieces
        strNewInnerHtml.append(textOriginal.Substring(i,strPiece.Length)
        strNewInnerHtml.append("<span style=""background-color:yellow"">" & searchString & "</span>")
        i += strPiece.Length + searchString.Length
    Next

        If textToLower.IndexOf(searchString) <> -1 Then
            wbContent.Document.Body.InnerHtml = strNewInnerHtml.ToString()
        Else
            MessageBox.Show(searchString & " is not located in this text!")
        End If

        txtSearch.Text = String.Empty
   End If

答案 1 :(得分:1)

您可以使用string.Replace(...)扩展方法,以下是一个示例C#代码(VB代码版本在此帖子的P.S.中):

using System;
using System.Text;

namespace StringClassExtensions
{
    public static class StringReplaceExtension
    {
        public static string Replace(this string str,
                                     string oldValue, string newValue,
                                     StringComparison comparisonType)
        {
            const int maxCapacity = 16777215;
            if (string.IsNullOrEmpty(str)) return str;
            if (string.IsNullOrEmpty(newValue)) return str;
            if (oldValue == null) throw new ArgumentNullException("oldValue");
            if (oldValue.Length == 0) return str;
            if (str.Length > maxCapacity) throw new ArgumentException("'str' is too long");
            if (oldValue.Length > maxCapacity) throw new ArgumentException("'oldValue' is too long");
            if (newValue.Length > maxCapacity) throw new ArgumentException("'newValue' is too long");

            int currentSearchPosition, lastSearchStartPosition = 0;
            var returnValue = new StringBuilder(str.Length, maxCapacity);

            while ((currentSearchPosition = str.IndexOf(oldValue, lastSearchStartPosition, comparisonType)) >= 0)
            {
                if (currentSearchPosition >= lastSearchStartPosition)
                    returnValue.Append(str.Substring(lastSearchStartPosition, currentSearchPosition - lastSearchStartPosition) + newValue);
                lastSearchStartPosition = currentSearchPosition + oldValue.Length;
            }

            if (lastSearchStartPosition == 0) return str;
            if (lastSearchStartPosition < str.Length)
                returnValue.Append(str.Substring(lastSearchStartPosition));

            return returnValue.ToString();
        }
    }
}

并只编辑原始代码的一行:

textToSearch = textToSearch.Replace(searchString, "<span style=""background-color:yellow"">" & searchString & "</span>")

textToSearch = textToSearch.Replace(searchString, 
   "<span style=""background-color:yellow"">" & searchString + "</span>",
    StringComparison.InvariantCultureIgnoreCase)

注意:原始string.Replace(...)方法的代码发布在referencesource.microsoft.com和AFAIS上它使用有效的内部实现 - 只有当原始方法不是时,才使用此处发布的扩展方法&#t; t合适的。

P.S。这是我的示例String.Replace(...)方法的VB版本。我在developerFusion上通过自动转换获得了VB版本,然后我手动编辑了转换结果VB代码并进行了简单测试。它似乎运作良好。

Imports System.Text

Namespace StringClassExtensions
    Public Module StringReplaceExtension
        <System.Runtime.CompilerServices.Extension> _
        Public Function Replace(str As String, oldValue As String, newValue As String, comparisonType As StringComparison) As String
            Const maxCapacity As Integer = 16777215
            If String.IsNullOrEmpty(str) Then
                Return str
            End If
            If String.IsNullOrEmpty(newValue) Then
                Return str
            End If
            If oldValue Is Nothing Then
                Throw New ArgumentNullException("oldValue")
            End If
            If oldValue.Length = 0 Then
                Return str
            End If
            If str.Length > maxCapacity Then
                Throw New ArgumentException("'str' is too long")
            End If
            If oldValue.Length > maxCapacity Then
                Throw New ArgumentException("'oldValue' is too long")
            End If
            If newValue.Length > maxCapacity Then
                Throw New ArgumentException("'newValue' is too long")
            End If

            Dim currentSearchPosition As Integer, lastSearchStartPosition As Integer = 0
            Dim returnValue = New StringBuilder(str.Length, maxCapacity)

            While (InlineAssignHelper(currentSearchPosition, str.IndexOf(oldValue, lastSearchStartPosition, comparisonType))) >= 0
                If currentSearchPosition >= lastSearchStartPosition Then
                    returnValue.Append(str.Substring(lastSearchStartPosition, currentSearchPosition - lastSearchStartPosition) & newValue)
                End If
                lastSearchStartPosition = currentSearchPosition + oldValue.Length
            End While

            If lastSearchStartPosition = 0 Then
                Return str
            End If
            If lastSearchStartPosition < str.Length Then
                returnValue.Append(str.Substring(lastSearchStartPosition))
            End If

            Return returnValue.ToString()
        End Function
        Private Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
            target = value
            Return value
        End Function
    End Module
End Namespace

P.P.S。 string.Replace(...)方法扩展的测试套件

using System;
using System.Text;
using NUnit.Framework;
using StringClassExtensions;

namespace Unit_Tests_CS_ConsoleApplication1
{
    [TestFixture]
    public class Test_0001_StringReplaceMethodExtensionTests
    {
        [SetUp]
        public void TestSetup()
        { }
        [TearDown]
        public void TestTearDown()
        { }

        [Test]
        public void TestNullSourceString()
        {
            string testStr = null;
            string resultStr = testStr.Replace("oldValue", "newValue", StringComparison.InvariantCultureIgnoreCase);
            Assert.IsNull(resultStr);
        }

        [Test]
        public void TestEmptySourceString()
        {
            string testStr = string.Empty;
            string resultStr = testStr.Replace("oldValue", "newValue", StringComparison.InvariantCultureIgnoreCase);
            Assert.IsEmpty(resultStr);
        }

        [Test]
        public void TestNullNewValue()
        {
            string testStr = "Hello, World!";
            string resultStr = testStr.Replace("oldValue", null, StringComparison.InvariantCultureIgnoreCase);
            Assert.IsTrue(resultStr == testStr);
        }

        [Test]
        public void TestEmptyNewValue()
        {
            string testStr = "Hello, World!";
            string resultStr = testStr.Replace("oldValue", string.Empty, StringComparison.InvariantCultureIgnoreCase);
            Assert.IsTrue(resultStr == testStr);
        }

        [Test]
        public void TestNullOldValue()
        {
            Assert.Throws(typeof(ArgumentNullException),
                () =>
                {
                    string testStr = "Hello, World!";
                    string resultStr = testStr.Replace(null, "newValue", StringComparison.InvariantCultureIgnoreCase);
                }
                );
        }

        [Test]
        public void TestEmptyOldValue()
        {
            string testStr = "Hello, World!";
            string resultStr = testStr.Replace(string.Empty, "newValue", StringComparison.InvariantCultureIgnoreCase);
            Assert.IsTrue(resultStr == testStr);
        }

        [Test]
        public void TestOldValueIsMissingInTheSearchStr()
        {
            string testStr = "Hello, World!";
            string resultStr = testStr.Replace("oldValue", "newValue", StringComparison.InvariantCultureIgnoreCase);
            Assert.IsTrue(resultStr == testStr);
        }

        [Test]
        public void TestSearchStrEqualsToOldValue()
        {
            string testStr = "oldValue";
            string resultStr = testStr.Replace("oldValue", "newValue", StringComparison.InvariantCultureIgnoreCase);
            Assert.IsTrue(resultStr == "newValue");
        }

        [Test]
        public void TestSearchStrStartsWithOldValue()
        {
            string testStr = "oldValue + some words";
            string resultStr = testStr.Replace("oldValue", "newValue", StringComparison.InvariantCultureIgnoreCase);
            Assert.IsTrue(resultStr == "newValue + some words");
        }

        [Test]
        public void TestSearchStrEndsWithOldValue()
        {
            string testStr = "some words + oldValue";
            string resultStr = testStr.Replace("oldValue", "newValue", StringComparison.InvariantCultureIgnoreCase);
            Assert.IsTrue(resultStr == "some words + newValue");
        }

        [Test]
        public void TestSearchStrHasSeveralOccurrencesOfOldValueSeparatedByOtherChars()
        {
            string testStr = "some words + oldValue + some more words + oldValue + even more words";
            string resultStr = testStr.Replace("oldValue", "newValue", StringComparison.InvariantCultureIgnoreCase);
            Assert.IsTrue(resultStr == "some words + newValue + some more words + newValue + even more words");
        }

        [Test]
        public void TestSearchStrHasSeveralOccurrencesOfOldValueFollowingOneAfterAnother()
        {
            string testStr = "some words + oldValueoldValueoldValue + even more words";
            string resultStr = testStr.Replace("oldValue", "newValue", StringComparison.InvariantCultureIgnoreCase);
            Assert.IsTrue(resultStr == "some words + newValuenewValuenewValue + even more words");
        }

        [Test]
        public void TestCaseInsensitiveStringComparison()
        {
            string testStr = "some words + oldValue + OldValue + oldValue + even more words";
            string resultStr = testStr.Replace("oldValue", "newValue", StringComparison.InvariantCultureIgnoreCase);
            Assert.IsTrue(resultStr == "some words + newValue + newValue + newValue + even more words");
        }

        [Test]
        public void TestCaseSensitiveStringComparison()
        {
            string testStr = "some words + oldValue + OldValue + oldValue + even more words";
            string resultStr = testStr.Replace("oldValue", "newValue", StringComparison.InvariantCulture);
            Assert.IsTrue(resultStr == "some words + newValue + OldValue + newValue + even more words");
        }

        [Test]
        public void TestSourceStringIsOutOfMaxCapacity()
        {
            Assert.Throws(typeof(ArgumentException),
                () =>
                {
                    int testCapacity = new StringBuilder().MaxCapacity / 128 + 1;
                    string testStr = new string('A', testCapacity); 
                    string resultStr = testStr.Replace("oldValue", "newValue", StringComparison.InvariantCultureIgnoreCase);
                }
                );
        }


        [Test]
        public void TestOldValueIsOutOfMaxCapacity()
        {
            Assert.Throws(typeof(ArgumentException),
                () =>
                {
                    int testCapacity = new StringBuilder().MaxCapacity / 128 + 1;
                    string testStr = "Hello, World!";
                    string oldValue = new string('A', testCapacity);
                    string resultStr = testStr.Replace(oldValue, "newValue", StringComparison.InvariantCultureIgnoreCase);
                }
                );
        }

        [Test]
        public void TestNewValueIsOutOfMaxCapacity()
        {
            Assert.Throws(typeof(ArgumentException),
                () =>
                {
                    int testCapacity = new StringBuilder().MaxCapacity / 128 + 1;
                    string testStr = "Hello, World!";
                    string newValue = new string('A', testCapacity);
                    string resultStr = testStr.Replace("oldValue", newValue, StringComparison.InvariantCultureIgnoreCase);
                }
                );
        }


        [Test]
        public void TestResultStringIsOutOfMaxCapacity()
        {
            Assert.Throws(typeof(ArgumentOutOfRangeException),
                () =>
                {
                    string oldValue = "Hello, World!";
                    int testCapacity = new StringBuilder().MaxCapacity / 128 - oldValue.Length;
                    string testStr = oldValue + new string('A', testCapacity);
                    string newValue = "Hello, the New World!";
                    string resultStr = testStr.Replace(oldValue, newValue, StringComparison.InvariantCultureIgnoreCase);
                }
                );
        }
    }
}

答案 2 :(得分:0)

替换文本将不起作用,相反,您只需将范围标签放在搜索到的文本之前和之后。这可能需要进行如下更改。

Private Sub WebBrowser_DocumentCompleted(sender As Object, e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles WebBrowser.DocumentCompleted
    Dim doc2 As mshtml.IHTMLDocument2 = WebBrowser.Document.DomDocument
    Dim ReplacementTag As String = "<span style='background-color: rgb(255, 255, 0);'>"
    Dim strBuilder As StringBuilder = New StringBuilder(doc2.body.outerHTML)
    Dim HTMLString As String = strBuilder.ToString()
    If Me.m_NoteType = ExtractionNoteType.SearchResult Then
        Dim SearchWords As New List(Of String)
        SearchWords.AddRange(Me.txtSearch.Text.Trim.Split(" "))
        For Each item As String In SearchWords
            Dim index As Integer = HTMLString.IndexOf(item, 0, StringComparison.InvariantCultureIgnoreCase)
            ''If index > 0 Then
            While (index > 0 AndAlso index < HTMLString.Length)
                HTMLString = HTMLString.Insert(index, ReplacementTag)
                HTMLString = HTMLString.Insert(index + item.Length + ReplacementTag.Length, "</span>")
                index = HTMLString.IndexOf(item, index + item.Length + ReplacementTag.Length + 7, StringComparison.InvariantCultureIgnoreCase)
            End While
            ''End If
            ''strBuilder.Replace(item, "<span style='background-color: rgb(255, 255, 0);'>" + item + "</span>")
        Next
    Else
        ''strBuilder.Replace("<span style='background-color: rgb(255, 255, 0);'>", "<span style='background-color: rgb(255, 255, 255);'>")
    End If
    doc2.body.innerHTML = HTMLString
End Sub