【发布时间】:2021-01-15 18:23:17
【问题描述】:
我需要用星号替换 HTML 标记(不是 HTML 内容)中的文本匹配项。此 HTML 标记也可能是嵌套的。例如:
<span class='lorem'>Lorem ipsum</span>
结果应该是:
<span class='*****'>Lorem ipsum</span>
或者对于嵌套的:
<p class='lorem'>Lorem<span id='ipsum'>ipsum</span></p>
结果应该是:
<p class='*****'>Lorem<span id='*****'>ipsum</span></p>
我为此创建了一个方法,但它仅适用于未嵌套的 HTML 标签:
/// <summary>
/// Sanitizes the source by replacing any value matching the param text within HTML Tag with asterisks.
/// This ensures that only HTML content will be considered.
/// </summary>
/// <param name="s">The source to look for Html Tags.</param>
/// <param name="text">The text to be looked for in the source.</param>
/// <returns>Source with sanitized HTML, if any. If no HTML was found returns the source itself.</returns>
private static string SanitizeSource(string s, string text)
{
var regex = new Regex("<(.*)>(.*?)</(.*?)>");
var m = regex.Match(s);
if (!m.Success) {
return s;
}
var tagStart = m.Groups[1].Value.Replace(text, new string('*', text.Length), StringComparison.OrdinalIgnoreCase);
var tagContent = m.Groups[2].Value;
var tagEnd = m.Groups[3].Value;
var newSource = $"<{tagStart}>{tagContent}</{tagEnd}>";
return newSource;
}
我想递归调用这个方法总是寻找嵌套的 HTML 标签,但我想知道是否有更优雅的方法?
编辑:
根据答案,上面的代码变成了:
private static string SanitizeSource(string s, string text)
{
var result = Regex.Replace(s, "(?<==('|\"))(.*?)(?=(\\1))", new string('*', text.Length));
return result;
}
我仍在处理一些边缘情况,例如字符串:
"<img src="http://lorem.png" />Lorem ipsum dolor sit amet, consectetur adipiscing elit."
应该变成:
"<img src="http://*****.png" />Lorem ipsum dolor sit amet, consectetur adipiscing elit."
目前该模式正在删除等号 = 之后的所有内容。
编辑:
在寻找一个干净的解决方案并自己尝试之后,我发现尝试使用 RegExp 处理 HTML 字符串很容易出错。尽管我之前在 StackOverflow 上找到了一些链接,但我仍然不确定这是否好。确实HtmlAgilityPack 是我最好的选择。
【问题讨论】:
-
你不应该使用正则表达式来解析 HTML:stackoverflow.com/questions/1732348/…
-
@ChristianBaumann 谢谢,但我看不到我在哪里解析 HTML。这是一个字符串匹配。
-
这是在 html 文件上还是来自网站的 html,还是嵌套在 html 中?如果是这样,正则表达式并不适合
-
更优雅的方式是使用 HtmlAgilityPack。请参阅:stackoverflow.com/questions/36711680/… 了解如何按类名查找。 HtmlAgilityPack 也可以通过 id 找到。
-
它来自 REST Api 的字符串输入。我没有解析任何东西,也不需要。