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

C# .NET Core下如何快速替换XML属性中未正确转义的<和>符号

C# .NET Core 修复XML未转义尖括号的可行方案

核心前提说明

直接全局替换</>不可行,会破坏合法的XML标签、处理指令、注释等结构的尖括号,必须基于XML上下文判断尖括号是否需要转义。

方案1:使用容错XML解析库(最稳定,兼容任意结构)

推荐使用AngleSharp.Xml库,它原生支持解析非规范XML,自动识别并修复未转义的属性值、文本内容中的尖括号,不需要手动处理不同结构的差异。

实现步骤

  1. 安装NuGet包:AngleSharp.Xml
  2. 代码示例:
using AngleSharp;
using AngleSharp.Xml.Parser;

// 配置解析器,开启容错模式
var context = BrowsingContext.New(Configuration.Default.WithXml());
var parser = context.GetService<IXmlParser>();
var options = new XmlParserOptions
{
    IsSupportingProcessingInstructions = true,
    IsKeepingSourceReferences = false,
    // 开启容错,自动修复未转义字符
    IsSuppressingErrors = true
};

// 读取破损XML
var brokenXml = File.ReadAllText("你的XML文件路径");
// 解析并自动修复
var document = parser.ParseDocument(brokenXml, options);
// 导出规范XML
File.WriteAllText("修复后的输出路径.xml", document.ToXml());

该方案对XML结构无要求,自动处理属性、文本节点内的未转义尖括号,适合绝大多数场景。

方案2:逐字符状态机处理(适合GB级大体积文件,低内存占用)

针对大体积XML文件,逐字符读取并跟踪当前上下文状态,仅转义非合法标签位置的尖括号,内存占用稳定在KB级,不受文件大小限制。

状态机逻辑说明

跟踪3种核心状态:

  • 普通文本/属性值内:遇到</>直接转义
  • 标签内部:仅识别合法标签字符,遇到异常</>判定为需要转义
  • 特殊段(CDATA、注释、处理指令):内部的</>不需要处理

代码示例:

using System.Text;

public static void RepairLargeXml(string inputPath, string outputPath)
{
    using var reader = new StreamReader(inputPath, Encoding.UTF8);
    using var writer = new StreamWriter(outputPath, false, Encoding.UTF8);
    var state = ParseState.Normal;
    var tagBuffer = new StringBuilder();
    
    while (!reader.EndOfStream)
    {
        var c = (char)reader.Read();
        switch (state)
        {
            case ParseState.Normal:
                if (c == '<')
                {
                    // 预读判断是不是合法标签开头
                    var next = (char)reader.Peek();
                    if (char.IsLetter(next) || next == '/' || next == '!' || next == '?')
                    {
                        // 合法标签开头,直接写
                        writer.Write(c);
                        state = ParseState.InTag;
                        tagBuffer.Clear();
                    }
                    else
                    {
                        // 未转义的<,转义
                        writer.Write("&lt;");
                    }
                }
                else if (c == '>')
                {
                    // 普通文本里的>需要转义
                    writer.Write("&gt;");
                }
                else
                {
                    writer.Write(c);
                }
                break;
            case ParseState.InTag:
                if (c == '>')
                {
                    // 标签结束
                    writer.Write(c);
                    state = ParseState.Normal;
                }
                else if (c == '\"' || c == '\'')
                {
                    // 进入属性值
                    writer.Write(c);
                    state = c == '\"' ? ParseState.InDoubleQuoteAttr : ParseState.InSingleQuoteAttr;
                }
                else if (c == '<')
                {
                    // 标签内出现异常<,转义
                    writer.Write("&lt;");
                }
                else
                {
                    tagBuffer.Append(c);
                    writer.Write(c);
                }
                break;
            case ParseState.InDoubleQuoteAttr:
                if (c == '"')
                {
                    writer.Write(c);
                    state = ParseState.InTag;
                }
                else if (c == '<')
                {
                    writer.Write("&lt;");
                }
                else if (c == '>')
                {
                    writer.Write("&gt;");
                }
                else
                {
                    writer.Write(c);
                }
                break;
            case ParseState.InSingleQuoteAttr:
                if (c == '\'')
                {
                    writer.Write(c);
                    state = ParseState.InTag;
                }
                else if (c == '<')
                {
                    writer.Write("&lt;");
                }
                else if (c == '>')
                {
                    writer.Write("&gt;");
                }
                else
                {
                    writer.Write(c);
                }
                break;
        }
    }
}

enum ParseState
{
    Normal,
    InTag,
    InDoubleQuoteAttr,
    InSingleQuoteAttr
}

如果需要支持CDATA、注释等特殊结构,扩展对应的状态分支即可。

注意事项

  1. 修复前务必备份原文件,避免不可逆的结构损坏
  2. 你提供的示例中存在根标签前后不匹配的问题(开标签是rootXML,关标签是tootXML),上述方案1的容错解析会自动识别并提示该类错误,可根据需求选择是否同步修复
  3. 若XML中存在大量CDATA段,优先使用方案1,避免自定义状态机漏处理特殊场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 08:57:03