【问题标题】:Searching for a text in a string property where the value is HTML在值为 HTML 的字符串属性中搜索文本
【发布时间】:2019-07-31 09:33:51
【问题描述】:

我的数据库 (SQL Server) 中有一个类型为 nvarchar(max) 的字段,其值为 HTML(比如电子邮件的内容)。

我想通过给定文本搜索这些值。我使用.net core 和Entity framework 进行查询。

当然,我可以简单地使用Contains 函数,但它也包含HTML 标记。例如,如果我搜索文本“strong”,它也会匹配那些具有强 HTML 标记的值,尽管它们的内容中可能没有 strong 这个词,这是不可取的。

var query = _dbContext.Emails.AsQueryable();

// The following code also searches through HTML tags
if(!string.IsNullOrWhiteSpace(searchText))
{
    query=query.Where(ent=>ent.Contents.Contains(searchText));
}

有没有一种简单的方法可以避免在搜索中使用 HTML 标记,例如使用 Regex?

更新

理想情况下,当查询是IQueryable 而不是IEnumerable 时,即在调用.ToList() 之前,我想在SQL 服务器端执行此操作。

【问题讨论】:

  • HTML 不是正则的,Regex 是用来解析正则表达式的。所以我们不建议在 html 上使用正则表达式。最好使用 HTML 库从 html 中获取标签/数据。
  • 先剥离 html 标签。网络上有很多功能可以做到这一点。
  • 也许使用 '>...

标签: c# linq .net-core


【解决方案1】:

我认为您的情况没有简单的答案,但您有多种可能性。如果您不想获得完整的标签,Regex 可以是一个简单的解决方案。更深入但更复杂的是使用 HtmlAgilityPack 之类的包来解析您的邮件。

这是一个正则表达式的例子:

var searchWord = "strong";
var mail = "<strong>blablabla</strong><p>blabla strong blabla</p>";
var rgx = new Regex($"(?!<){searchWord}(?!>)"); // Will match strong but not <strong> or <strong or strong>
if (rgx.IsMatch(mail))
{
    // Do what you want
}

【讨论】:

    【解决方案2】:

    看看你是否可以使用免费开源的HtmlAgilityPack,通过它你可以先将html文本转换为纯文本,然后应用搜索条件。

    例如:var plainTextResult = HtmlUtilities.ConvertToPlainText(string html);

    if(!string.IsNullOrWhiteSpace(searchText))
    {
        bool containsResult = plainTextResult.Contains(searchText);
    }
    

    【讨论】:

      【解决方案3】:

      感谢@Amine 和@lollmbaowtfidgafgtfoohwtbs,我想出了如何做到这一点。

      首先,我在我的数据库中创建了一个删除给定文本的 SQL 函数:

      
      CREATE FUNCTION [dbo].[ufnStripHTML] (@HTMLText NVARCHAR(MAX))
      RETURNS NVARCHAR(MAX) AS
      BEGIN
          DECLARE @Start INT
          DECLARE @End INT
          DECLARE @Length INT
          SET @Start = CHARINDEX('<',@HTMLText)
          SET @End = CHARINDEX('>',@HTMLText,CHARINDEX('<',@HTMLText))
          SET @Length = (@End - @Start) + 1
          WHILE @Start > 0 AND @End > 0 AND @Length > 0
          BEGIN
              SET @HTMLText = STUFF(@HTMLText,@Start,@Length,'')
              SET @Start = CHARINDEX('<',@HTMLText)
              SET @End = CHARINDEX('>',@HTMLText,CHARINDEX('<',@HTMLText))
              SET @Length = (@End - @Start) + 1
          END
          RETURN LTRIM(RTRIM(@HTMLText))
      END
      GO
      

      然后我在DbContext 中添加了对该函数的引用:

              [DbFunction("ufnStripHTML")]
              public static string StripHTML(string text)
              {
                  throw new Exception("not implemented");
              }
      

      现在我可以在我的Linq to SQL 查询中使用它:

      
      if (!string.IsNullOrWhiteSpace(searchText))
      {
          query = query.Where(ent => TGDbContext.StripHTML(ent.Contents).Contains(searchText));
      }
      

      【讨论】:

        【解决方案4】:

        您可以像下面这样使用正则表达式函数:

        "<div>Hello</div><span>World</span>".replace(/<[^>]*>/g, '')
        

        【讨论】:

        • 您在这里使用什么语言?它不是 C#。
        • 该示例包含您需要的正则表达式,这只是一个示例,我相信您只需在 C# 代码中使用该正则表达式来替换第一个 Html,然后您就可以使用 IndexOf() 函数。我希望这是有道理的。不要给我负面反馈,我只是想帮助你。
        • 谢谢@Mahesh。我没有给你负面的反馈。别人做了!
        • @Mojtaba 也给你
        猜你喜欢
        • 2018-12-14
        • 1970-01-01
        • 1970-01-01
        • 2011-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多