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

.NET 6+中能否配置XmlSerializer接受空字符?

.NET 7中XmlSerializer兼容空字符序列化解决方案

问题背景

以下是最小复现代码:

using System;
using System.IO;
using System.Xml.Serialization;

public class Program
{
    public class C { public string S { get; set; } }

    public static void Main()
    {
        var serializer = new XmlSerializer(typeof(C));
        C data = new C() { S = "a\0b" };

        using (var sw = new StringWriter())
        {
            serializer.Serialize(sw, data);
            Console.WriteLine(sw.ToString());
        }
    }
}

不同.NET版本表现

  • 在.NET Framework 4.x 和 .NET 5中,代码会生成包含空字符转义的XML输出:
<?xml version="1.0" encoding="utf-16"?>
<C xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <S>a&#x0;b</S>
</C>
  • 在.NET 6和7中,会抛出异常:
Unhandled exception. System.InvalidOperationException: There was an error generating the XML document.
 ---> System.ArgumentException: '.', hexadecimal value 0x00, is an invalid character.
   at System.Xml.XmlEncodedRawTextWriter.WriteElementTextBlock(Char* pSrc, Char* pSrcEnd)
   at System.Xml.XmlEncodedRawTextWriter.WriteString(String text)
   at System.Xml.XmlWellFormedWriter.WriteString(String text)
   at System.Xml.Serialization.XmlSerializationWriter.WriteElementString(String localName, String ns, String value, XmlQualifiedName xsiType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterC.Write2_C(String n, String ns, C o, Boolean isNullable, Boolean needType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterC.Write3_C(Object o)
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
   --- End of inner exception stack trace ---
   at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
   at Program.Main()

空字符本身不属于XML规范中的有效字符,.NET 6+的行为变更符合规范,但如果你的场景是仅内部使用XmlSerializer序列化/反序列化,不在意XML合规性,则需要解决这个兼容性问题(已知反序列化时,给XmlTextReader设置Normalization = false即可解析转义后的空字符)。

核心需求:在.NET 7中让XmlSerializer接受空字符并生成转义后的XML

解决方案

XmlSerializer没有直接的配置项允许空字符,但可以通过自定义XmlWriter绕过有效性检查,手动处理空字符转义:

1. 自定义XmlWriter类

public class NullAllowedXmlTextWriter : XmlTextWriter
{
    public NullAllowedXmlTextWriter(TextWriter writer) : base(writer) { }

    public override void WriteString(string text)
    {
        if (string.IsNullOrEmpty(text))
        {
            base.WriteString(text);
            return;
        }

        int startIndex = 0;
        for (int i = 0; i < text.Length; i++)
        {
            char currentChar = text[i];
            // 处理空字符,转义为&#x0;
            if (currentChar == '\0')
            {
                if (i > startIndex)
                    base.WriteString(text.Substring(startIndex, i - startIndex));
                base.WriteRaw("&#x0;");
                startIndex = i + 1;
            }
            // 保留默认的XML特殊字符转义逻辑
            else if (currentChar is '<' or '>' or '&' or '"' or '\'')
            {
                if (i > startIndex)
                    base.WriteString(text.Substring(startIndex, i - startIndex));
                base.WriteCharEntity(currentChar);
                startIndex = i + 1;
            }
        }

        // 写入剩余的正常字符
        if (startIndex < text.Length)
            base.WriteString(text.Substring(startIndex));
    }
}

2. 使用自定义XmlWriter进行序列化

修改序列化代码,替换默认的写入器:

public static void Main()
{
    var serializer = new XmlSerializer(typeof(C));
    C data = new C() { S = "a\0b" };

    using (var sw = new StringWriter())
    using (var xmlWriter = new NullAllowedXmlTextWriter(sw))
    {
        serializer.Serialize(xmlWriter, data);
        Console.WriteLine(sw.ToString());
    }
}

修改后,在.NET 7中就能生成与旧版本一致的XML输出,且能和你现有的反序列化逻辑兼容。

注意:此方式生成的XML不符合官方规范,仅适合内部自用场景,不要用于和第三方XML系统交互。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 22:35:18