c#


Search keyword highlight in ASP.Net


I am outputting a list of search results for a given string of keywords, and I want any matching keywords in my search results to be highlighted. Each word should be wrapped in a span or similar. I am looking for an efficient function to do this.
E.g.
Keywords: "lorem ipsum"
Result: "Some text containing lorem and ipsum"
Desired HTML output: "Some text containing <span class="hit">lorem</span> and <span class="hit">ipsum</span>"
My results are case insensitive.
Here's what I've decided on. An extension function that I can call on the relevant strings within my page / section of my page:
public static string HighlightKeywords(this string input, string keywords)
{
if (input == string.Empty || keywords == string.Empty)
{
return input;
}
string[] sKeywords = keywords.Split(' ');
foreach (string sKeyword in sKeywords)
{
try
{
input = Regex.Replace(input, sKeyword, string.Format("<span class=\"hit\">{0}</span>", "$0"), RegexOptions.IgnoreCase);
}
catch
{
//
}
}
return input;
}
Any further suggestions or comments?
try highlighter from Lucene.net
http://incubator.apache.org/lucene.net/docs/2.0/Highlighter.Net/Lucene.Net.Highlight.html
How to use:
http://davidpodhola.blogspot.com/2008/02/how-to-highlight-phrase-on-results-from.html
EDIT:
As long as Lucene.net highlighter is not suitable here new link:
http://mhinze.com/archive/search-term-highlighter-httpmodule/
Use the jquery highlight plugin.
For highlighting it at server side
protected override void Render( HtmlTextWriter writer )
{
StringBuilder html = new StringBuilder();
HtmlTextWriter w = new HtmlTextWriter( new StringWriter( html ) );
base.Render( w );
html.Replace( "lorem", "<span class=\"hit\">lorem</span>" );
writer.Write( html.ToString() );
}
You can use regular expressions for advanced text replacing.
You can also write the above code in an HttpModule so that it can be re used in other applications.
I got a similar requirement to do in ASP.NET.Here is my solution written in C# for highlight keyword.
Algo used is Naive search algorithm.
Maintain a hashtable to store matches.
Apply Tags on the string where there is a keyword match.
region Highlighting
/// <summary>
/// Higlight the search term.
/// </summary>
/// <param name="currentString"></param>
/// <returns></returns>
private string Highlight(string currentString)
{
try
{
var termValue = _helperRequest.SearchText;
if (!string.IsNullOrEmpty(currentString) && !string.IsNullOrEmpty(termValue))
{
currentString = termValue.Trim().Split(Constants.Separator)
.ToList().Where(x => x.Length >1)
.Distinct()
.OrderByDescending(x => x.Length)
.Aggregate(currentString, (current, keyWord) =>
TagIndexers(new SearchHelperRequest() { SearchString = current, SearchTerm = keyWord, HightlightCss = _helperRequest.HightlightCss, Comparison = StringComparison.InvariantCultureIgnoreCase, TagIdentifier = GetRandomKey() }));
}
}
catch (Exception ex)
{
Logger.WriteError(string.Format("Highlight Error : {0}", ex.Message));
}
finally
{
//Replace tags with highlight terms.
if (_helperRequest != null)
{
if (_helperRequest.TagKeyLookup.Keys.Count > 0)
{
foreach (string tagKey in _helperRequest.TagKeyLookup.Keys)
{
if (!string.IsNullOrEmpty(currentString))
currentString = currentString.Replace(tagKey, _helperRequest.TagKeyLookup[tagKey]);
}
//clear the key list.
_helperRequest.TagKeyLookup.Clear();
}
}
}
return HttpUtility.JavaScriptStringEncode(currentString);
}
/// <summary>
/// Generate a randome key from lookup table. Recurrsive in nature.
/// </summary>
/// <returns></returns>
private string GetRandomKey()
{
//config your key length
var charBuffer = new char[4];
lock (charBuffer)
{
for (var iCounter = 0; iCounter < charBuffer.Length; iCounter++)
{
charBuffer[iCounter] = CharacterLookup
[new Random().Next(CharacterLookup.Length)];
}
}
//Recurssion to generate random.
return _helperRequest.TagKeyLookup.
ContainsKey(new String(charBuffer))
? GetRandomKey() : new String(charBuffer);
}
/// <summary>
/// Replace the term with identifiers
/// </summary>
/// <param name="searchRequest"></param>
/// <returns></returns>
private string TagIndexers(SearchHelperRequest searchRequest)
{
try
{
var highlightBulder = new StringBuilder();
string spanValue = string.Empty;
if (!string.IsNullOrEmpty(searchRequest.SearchString) && !string.IsNullOrEmpty(searchRequest.SearchTerm))
{
int previousIndex = 0;
int currentIndex = searchRequest.SearchString.IndexOf(searchRequest.SearchTerm, searchRequest.Comparison);
while (currentIndex != -1)
{
highlightBulder.Append(searchRequest.SearchString.Substring(previousIndex, currentIndex - previousIndex));
spanValue = string.Format(searchRequest.HightlightCss, searchRequest.SearchString.Substring(currentIndex, searchRequest.SearchTerm.Length));
highlightBulder.Append(searchRequest.TagIdentifier);
currentIndex += searchRequest.SearchTerm.Length;
previousIndex = currentIndex;
currentIndex = searchRequest.SearchString.IndexOf(searchRequest.SearchTerm, currentIndex, searchRequest.Comparison);
}
if (!_helperRequest.TagKeyLookup.ContainsKey(searchRequest.TagIdentifier) &&
!string.IsNullOrEmpty(spanValue))
{
_helperRequest.TagKeyLookup.Add(searchRequest.TagIdentifier, spanValue);
}
highlightBulder.Append(searchRequest.SearchString.Substring(previousIndex));
}
return highlightBulder.ToString();
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
private static char[] _characterLookup = null;
public char[] CharacterLookup
{
get
{
if (_characterLookup == null)
{
_characterLookup = new char[36];
lock (_characterLookup)
{
int indexer = 0;
//build the table.
for (char c = '0'; c <= '9'; c++) _characterLookup[indexer++] = c;
for (char c = 'A'; c <= 'Z'; c++) _characterLookup[indexer++] = c;
}
}
return _characterLookup;
}
}
**Summary of the Routines :
Search the Term and apply tags.
Store unique tags in a hashtable.
Replace the Tags with Span Highlights.**
An extension to the answer above. (don't have enough reputation to give comment)
To avoid span from being replaced when search criteria were [span pan an a], the found word was replaced to something else than replace back... not very efficient though...
public string Highlight(string input)
{
if (input == string.Empty || searchQuery == string.Empty)
{
return input;
}
string[] sKeywords = searchQuery.Replace("~",String.Empty).Replace(" "," ").Trim().Split(' ');
int totalCount = sKeywords.Length + 1;
string[] sHighlights = new string[totalCount];
int count = 0;
input = Regex.Replace(input, Regex.Escape(searchQuery.Trim()), string.Format("~{0}~", count), RegexOptions.IgnoreCase);
sHighlights[count] = string.Format("<span class=\"highlight\">{0}</span>", searchQuery);
foreach (string sKeyword in sKeywords.OrderByDescending(s => s.Length))
{
count++;
input = Regex.Replace(input, Regex.Escape(sKeyword), string.Format("~{0}~", count), RegexOptions.IgnoreCase);
sHighlights[count] = string.Format("<span class=\"highlight\">{0}</span>", sKeyword);
}
for (int i = totalCount - 1; i >= 0; i--)
{
input = Regex.Replace(input, "\\~" + i + "\\~", sHighlights[i], RegexOptions.IgnoreCase);
}
return input;
}

Related Links

C# protected readonly autoproperty with only a get accessor vs protected readonly field
c# Crystal report .NET object as Data source
How to insert numbers from line into array in Collection
Don't show read only dialog when opening a word document
Does PLINQ really not preserve order?
How do I correlate a Linq query extension method to its signature in the documentation?
Datagridview event not firing
How do I redistribute Microsoft.AnalysisServices.SPClient.Interfaces
Get Standard Touchpad Swipe
How to calculate the sum of the datatable column in c#
System.ArgumentException “Parameter is not valid” when comparing image dimensions
Set field via class
how to use ModelState.IsValid in ASP.NET?
protobuf-net : v2 deserialize v1 objects with inheritance
Getting data on ListView Select event and setting it in a div in C#
c# Oledb add list of parameters in a foreach loop

Categories

HOME
model-view-controller
alasql
sql-server-2014
cxf
microcontroller
c++builder
liquibase
azure-database-mysql
crm
ebay
sdk
uml-designer
collision-detection
cdn
rtc
ejb-3.0
google-my-business-api
websharper
expo
aggregate
internet-explorer-7
alert
project-reactor
caldav
keystone
gomobile
email-client
prepros
struts
nsopenpanel
rollupjs
windows-mobile
drombler-fx
scripting-language
csproj
paper-trail-gem
foxpro
blockly
circle
leaderboard
scip
anypoint-studio
const
ssdp
autodesk-data-management
paperclip
synchronized
anonymous-function
history
lucee
beanshell
openidm
fluent-nhibernate-mapping
r-commander
typewriter
hellosign
reloaddata
dynatable
boost-range
disconnect
geokit
git-cherry-pick
vitamio
diameter-protocol
bluetooth-lowenergy-4.2
sqldataadapter
redquerybuilder
openhab
pagecontrol
optimistic-locking
static-files
drools-guvnor
grunt-contrib-connect
novell
ios-enterprise
atg-dynamo
rda
azure-caching
new-operator
xcode5.1
google-oauth-java-client
angularjs-select2
mandelbrot
pyxplot
latex-suite
exi
coinbase-php
junction-table
spawn
simplemembership
pymel
reference-manual
antixsslibrary
screensharing
quit
blackberry-eclipse-plugin
beep
joomla1.7
scriptmanager
response-time
nstoolbar
chromebug
dongle
web-widget
pixel-bender
cstring
jgrowl

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App