You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从.NET 6 MVC的CSHTML文件提取静态文本内容?

提取.NET 6 MVC项目CSHTML中的静态文本(排除动态内容)

需求背景

需要从.NET 6 MVC的CSHTML视图文件中批量提取静态文本(按钮文本、标题、span内容、属性内的静态文本等),排除数据库/API返回的动态内容(如data-bind绑定值、ViewBag/Razor动态表达式渲染内容),用于多语言翻译的手动处理。

方案1:自定义C#控制台程序(推荐)

利用HtmlAgilityPack解析HTML内容,配合文本预处理过滤Razor动态代码,精准提取静态文本。

步骤1:安装依赖

在控制台项目中安装NuGet包:

Install-Package HtmlAgilityPack

步骤2:核心代码实现

using HtmlAgilityPack;
using System.Text.RegularExpressions;

class CsHtmlStaticTextExtractor
{
    static void Main(string[] args)
    {
        // 替换为你的CSHTML文件根目录
        string rootDir = @"C:\YourMvcProject\Views";
        var allStaticTexts = new HashSet<string>(); // 自动去重

        // 遍历所有.cshtml文件
        foreach (var file in Directory.EnumerateFiles(rootDir, "*.cshtml", SearchOption.AllDirectories))
        {
            string content = File.ReadAllText(file);
            var texts = ExtractStaticTextsFromCsHtml(content);
            foreach (var text in texts)
            {
                if (!string.IsNullOrWhiteSpace(text))
                {
                    allStaticTexts.Add(text.Trim());
                }
            }
        }

        // 输出结果到文件
        File.WriteAllLines("StaticTexts.txt", allStaticTexts.OrderBy(t => t));
        Console.WriteLine($"提取完成,共{allStaticTexts.Count}条静态文本");
    }

    static IEnumerable<string> ExtractStaticTextsFromCsHtml(string csHtmlContent)
    {
        // 1. 预处理:移除Razor代码块中的动态逻辑,保留块内HTML内容
        string processedContent = Regex.Replace(csHtmlContent, @"@\s*(if|else|foreach|for|while)\s*\([^)]*\)\s*\{\s*", "", RegexOptions.Singleline);
        processedContent = Regex.Replace(processedContent, @"}\s*else\s*\{\s*", "", RegexOptions.Singleline);
        processedContent = Regex.Replace(processedContent, @"}\s*", "", RegexOptions.Singleline);

        // 2. 移除Razor动态表达式(如@ViewBag.xxx、@Model.xxx)
        processedContent = Regex.Replace(processedContent, @"@\s*(\w+\.)+\w+", "", RegexOptions.Singleline);

        // 3. 使用HtmlAgilityPack解析HTML
        var doc = new HtmlDocument();
        doc.LoadHtml(processedContent);

        // 4. 提取文本节点,排除data-bind元素的空占位文本,保留静态fallback内容
        var textNodes = doc.DocumentNode.SelectNodes("//text()")?.Where(node =>
        {
            var parent = node.ParentNode;
            if (parent.Attributes["data-bind"] != null)
            {
                return !string.IsNullOrWhiteSpace(node.InnerText.Trim());
            }
            return true;
        });

        if (textNodes != null)
        {
            foreach (var node in textNodes)
            {
                var parts = node.InnerText.Split(new[] { '\n', '\r', '\t', '<', '>' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (var part in parts)
                {
                    var trimmed = part.Trim();
                    if (!string.IsNullOrWhiteSpace(trimmed))
                    {
                        yield return trimmed;
                    }
                }
            }
        }

        // 5. 提取data-content等属性内的HTML文本
        var attrNodes = doc.DocumentNode.SelectNodes("//@*[contains(name(), 'data-')]")?.Where(attr =>
        {
            return attr.Value.Contains("<div") || attr.Value.Contains("<span");
        });

        if (attrNodes != null)
        {
            foreach (var attr in attrNodes)
            {
                var innerDoc = new HtmlDocument();
                innerDoc.LoadHtml(attr.Value);
                var innerTexts = innerDoc.DocumentNode.SelectNodes("//text()");
                if (innerTexts != null)
                {
                    foreach (var innerText in innerTexts)
                    {
                        var trimmed = innerText.InnerText.Trim();
                        if (!string.IsNullOrWhiteSpace(trimmed))
                        {
                            yield return trimmed;
                        }
                    }
                }
            }
        }
    }
}

代码说明

  • 预处理阶段过滤Razor动态代码块和表达式,仅保留HTML结构与静态文本
  • 针对data-bind元素,保留其内部的静态fallback文本(如示例中的FirstText1、LASTTEXT)
  • 解析data-content等属性内的嵌套HTML,提取其中的静态文本
  • 自动去重并输出有序的静态文本列表

方案2:正则表达式快速提取(适合临时需求)

若无需复杂HTML解析,可使用正则快速提取静态文本,准确性略低于HtmlAgilityPack方案:

using System.Text.RegularExpressions;

class QuickExtractor
{
    static void Main(string[] args)
    {
        string rootDir = @"C:\YourMvcProject\Views";
        var allTexts = new HashSet<string>();

        foreach (var file in Directory.EnumerateFiles(rootDir, "*.cshtml", SearchOption.AllDirectories))
        {
            string content = File.ReadAllText(file);
            // 提取HTML标签内的静态文本
            var tagTexts = Regex.Matches(content, @"<[^>]+>([^<]+)</[^>]+>", RegexOptions.Singleline)
                .Cast<Match>()
                .Select(m => m.Groups[1].Value.Trim())
                .Where(t => !string.IsNullOrWhiteSpace(t) && !t.Contains("@") && !t.Contains("data-bind"));
            
            // 提取data-content属性内的文本片段
            var attrTexts = Regex.Matches(content, @"data-content=""[^""]+""", RegexOptions.Singleline)
                .Cast<Match>()
                .Select(m => Regex.Replace(m.Value, @"data-content=""|<[^>]+>|""", "").Trim())
                .SelectMany(t => t.Split(new[] { '.', '?', '!' }, StringSplitOptions.RemoveEmptyEntries))
                .Select(t => t.Trim())
                .Where(t => !string.IsNullOrWhiteSpace(t));

            foreach (var text in tagTexts.Concat(attrTexts))
            {
                allTexts.Add(text);
            }
        }

        File.WriteAllLines("QuickStaticTexts.txt", allTexts.OrderBy(t => t));
    }
}

注意事项

  1. 若需要提取@("静态文本")这类Razor静态字符串,可修改预处理逻辑,保留@("...")内的字符串内容
  2. 复杂嵌套HTML场景下,HtmlAgilityPack方案的准确性远高于正则
  3. 可根据项目实际情况调整正则或HTML选择器,比如添加更多需要排除的动态属性(如asp-for等)

内容的提问来源于stack exchange,提问作者Nagaajay k

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 10:15:02