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

C#:XmlDocument与XDocument处理无效十六进制字符的差异及咨询

XDocument与XmlDocument处理含十六进制实体XML的问题

我们在使用XDocument处理接收的XML文档时,遇到了由XmlDocument生成的、包含十六进制实体表达式的文档,XDocument.Parse()会直接拒绝处理这类文档。

XmlDocument的表现则完全不同:它既能将传入的控制字符编码生成含十六进制实体的XML文档,也能正常解析包含这些实体的XML;而XDocument无论是创建包含控制字符的文档,还是解析含十六进制实体的文档,都会抛出异常。

示例代码

static void Main(string[] args)
{
    string message = "Hello, \x1EWorld!"; // 包含控制码1E的字符串

    // 这段代码正常执行 - 创建包含控制字符的XML文档
    XmlDocument xmlDoc = new XmlDocument();
    XmlElement root = xmlDoc.CreateElement("greeting");
    xmlDoc.AppendChild(root);
    root.InnerText = message;
    Console.WriteLine(xmlDoc.OuterXml);

    // 输出: <greeting>Hello, &#x1E;World!</greeting>

    // 这段代码执行失败 - XDocument创建含控制字符的文档
    try
    {
        XDocument xdoc = new XDocument(
            new XElement("greeting", message)
        );
        Console.WriteLine(xdoc.ToString());
    }
    catch (Exception ex)
    {
        Console.WriteLine($"XDocument creation error: {ex}");
    }

    // 这段代码正常执行 - XmlDocument加载含十六进制实体的XML
    string xmlWithEscapedHexEntity = xmlDoc.OuterXml; // <greeting>Hello, &#x1E;World!</greeting>
    xmlDoc = new XmlDocument();
    xmlDoc.LoadXml(xmlWithEscapedHexEntity);
    Console.WriteLine(xmlDoc.OuterXml);

    // 这段代码执行失败 - XDocument解析含十六进制实体的XML
    try
    {
        XDocument xDoc = XDocument.Parse(xmlWithEscapedHexEntity);
        Console.WriteLine(xDoc.ToString());
    }
    catch (Exception ex)
    {
        Console.WriteLine($"XDocument parse failure: {ex}");
    }

    Console.ReadLine();
}

问题解答

1. 如何让XDocument处理这类含十六进制实体的XML?

有两种可靠的方法,比正则预处理更安全:

  • 用XmlDocument做中间转换:先通过XmlDocument加载XML字符串,再转换为XDocument。XmlDocument会先处理掉十六进制实体,转换后的XDocument就能正常操作:

    string xmlWithHexEntity = "<greeting>Hello, &#x1E;World!</greeting>";
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.LoadXml(xmlWithHexEntity);
    
    using (var reader = new XmlNodeReader(xmlDoc))
    {
        XDocument xDoc = XDocument.Load(reader);
        // 后续正常操作XDocument
    }
    
  • 关闭XmlReader的字符检查:创建XmlReader时设置CheckCharacters = false,这样XDocument加载时会跳过严格的字符规范检查,直接处理文档:

    XmlReaderSettings settings = new XmlReaderSettings();
    settings.CheckCharacters = false;
    
    using (XmlReader reader = XmlReader.Create(new StringReader(xmlWithHexEntity), settings))
    {
        XDocument xDoc = XDocument.Load(reader);
    }
    

    注意:关闭字符检查后,控制字符会保留在文档中,后续处理时需注意潜在问题。

    不建议用正则表达式预处理,因为XML结构复杂(比如CDATA区块、属性值等),正则容易误修改合法内容,导致XML损坏。

2. 为什么XDocument和XmlDocument有行为差异?

  • XmlDocument的设计兼容旧场景:它是.NET早期的XML处理组件,设计时更偏向兼容性,允许处理一些不符合严格XML规范的内容。比如XML 1.0规范中禁止的控制字符(U+0000到U+001F,除了换行、回车、制表符),XmlDocument会自动编码和解码,不会抛出异常。
  • XDocument严格遵循XML规范:作为LINQ to XML的核心组件,XDocument严格执行XML 1.0的规范,明确禁止这类控制字符出现在文档中(无论是直接字符还是实体引用)。一旦检测到不符合规范的内容,就会抛出异常,确保生成和解析的XML都是合法的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 13:40:08