关键字匹配特定条件时在文本中查找关键字 - C#

时间:2013-01-29 14:22:34

标签: html search tags conditional-statements keyword

我正在寻找一种很好的方法来执行以下操作:

我有一篇文章,其中包含HTML标签,如锚点和段落等 我也有关键字,我需要在文章中找到并将其设置为锚(我有一些网址设置) 如果关键字确实存在于文章中,那么它应该在使其成为锚之前匹配以下两个条件:

  1. 它不能在任何标签内。 例如,像

    <img alt="keyword"> 
    

    无效/匹配。

  2. 关键字不能已经在锚点内。例如,像

    这样的东西
    <a>keyword</a>
    

    无效/匹配。


    任何帮助,将不胜感激。 感谢

1 个答案:

答案 0 :(得分:1)

我已成功完成任务!

非常感谢这篇文章,它帮助了我很多xpath表达式: http://social.msdn.microsoft.com/Forums/en-US/regexp/thread/beae72d6-844f-4a9b-ad56-82869d685037/

我的任务是使用我的数据库中的关键字和网址表将X关键字添加到文章中。
一旦关键字匹配 - 它将不再搜索它,但会尝试在文本中找到下一个关键字。
'关键字'可以由多个单词组成。这就是我添加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);
    }
}

希望将来会帮助某人。