Я ищу хороший способ сделать следующее:
У меня есть статья, в которой есть HTML-теги, такие как якоря, абзацы и т. д.
У меня также есть ключевое слово, которое мне нужно найти в статье и установить его как якорь (у меня есть некоторый URL-адрес для установки там). Если ключевое слово существует в статье, оно должно соответствовать следующим ДВУМ условиям, ПРЕЖДЕ чем сделать его якорем:
Он не может быть внутри какого-либо тега. Например, что-то вроде
<img alt="keyword">
не будет действительным/сопоставленным.
Ключевое слово не может уже находиться внутри привязки. Например, что-то вроде
<a>keyword</a>
не будет действительным/сопоставленным.
Будем признательны за любую помощь. Спасибо
Ответ 1 · рейтинг 1 · YanivHer
Мне удалось это сделать!
Большое спасибо этому сообщению, которое очень помогло мне с выражением xpath: http://social.msdn.microsoft.com/Forums/en-US/regexp/thread/beae72d6-844f-4a9b-ad56-82869d685037/
Моя задача состояла в том, чтобы добавить X ключевых слов в статью, используя таблицу ключевых слов и URL-адресов в моей базе данных.
После совпадения ключевого слова - он не будет искать его снова, а попытается найти следующее ключевое слово в тексте.
Ключевое слово могло состоять из нескольких слов. Вот почему я добавил Replace(" ", "\s+").
Кроме того, сначала мне пришлось отдать предпочтение самым длинным ключевым словам. То есть, если бы у меня были:
"добрый день" и "хороший" как два разных ключевых слова - "добрый день" всегда побеждает.
Это мое решение:
static public string AddLinksToArticle(string article, int linksToAdd)
{
try
{
//load keywords and urls
var dt = new DAL().GetArticleLinks();
//sort the it
IEnumerable<ArticlesRow> sortedArticles = dt.OrderBy(row => row.keyword, new StringLengthComparer());
// iterate the dictionary to get keyword to replace with anchor
foreach (var item in sortedArticles)
{
article = FindAndReplaceKeywordWithAnchor(article, item.keyword, item.url, ref linksToAdd);
if (linksToAdd == 0)
{
break;
}
}
return article;
}
catch (Exception ex)
{
Utils.LogErrorAdmin(ex);
return null;
}
}
private static string FindAndReplaceKeywordWithAnchor(string article, string keyword, string url, ref int linksToAdd)
{
//convert text to html
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(article);
// \w* - means it can start with any alphanumeric charactar
// \s+ - was placed to replace all white spaces (when there is more than one word).
// \b - set bounderies for the keyword
string pattern = @"\b" + keyword.Trim().Insert(0, "\\w*").Replace(" ", "\\s+") + @"\b";
//get all elements text propery except for anchor element
var nodes = doc.DocumentNode.SelectNodes("//text()[not(ancestor::a)]") ?? new HtmlAgilityPack.HtmlNodeCollection(null);
foreach (var node in nodes)
{
if (node.InnerHtml.Contains(keyword))
{
Regex regex = new Regex(pattern);
node.InnerHtml = regex.Replace(node.InnerHtml, "<a href=\"" + url + "\">" + keyword + "</a>", 1);//match only first occurrence
linksToAdd--;
break;
}
}
return doc.DocumentNode.OuterHtml;
}
}
public class StringLengthComparer : IComparer<string>
{
public int Compare(string x, string y)
{
return y.Length.CompareTo(x.Length);
}
}
Надеюсь, это поможет кому-то в будущем.