【问题标题】:XML Deserialize special charactersXML反序列化特殊字符
【发布时间】:2026-02-15 14:50:01
【问题描述】:

我想反序列化一个在其中一个字段中具有特殊字符的 xml 文件。该字符为十六进制 0x05,并导致 xml 文件为 。 我能够序列化对象,但无法再次反序列化它。 我经常使用这种技术,但这是第一次它不起作用。 这是问题的一个最小示例:

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

namespace XMLTest
{
    class Program
    {
        static void Main(string[] args)
        {
            SpecialCharacter testobject = new SpecialCharacter();
            string filename = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\testfile.xml";

            //serialize
            StreamWriter writer = System.IO.File.CreateText(filename);
            XmlSerializer xmlserialize = new XmlSerializer(typeof(SpecialCharacter));
            xmlserialize.Serialize(writer, testobject);
            writer.Flush();
            writer.Close();

            //deserialize
            StreamReader reader = File.OpenText(filename);
            XmlSerializer xmldeserialize = new XmlSerializer(typeof(SpecialCharacter));
            testobject = (SpecialCharacter)xmldeserialize.Deserialize(reader);
            reader.Close();
        }
    }

    public class SpecialCharacter
    {
        public string special = char.ConvertFromUtf32(0x05).ToString();
    }
}

【问题讨论】:

    标签: c# xml serialization


    【解决方案1】:

    您必须使用将 Normalization 属性设置为 false 的特殊阅读器。

    所以不是

    StreamReader reader = File.OpenText(filename);
    

    使用

    XmlTextReader reader = new XmlTextReader(filename);
    

    现在应该可以了。

    【讨论】:

    • 微软似乎建议使用XmlReader 而不是XmlTextReader。两者都有效。 link
    【解决方案2】:

    这里有两个简单(-ish)的解决方案:

    • 使用XmlTextReader.Create 代替File.CreateText 并添加new XmlReaderSettings() { CheckCharacters = false } 作为第二个参数。不过,老实说,您可能应该避免这样做,除非您只是在处理自己创建的文件并且知道它们的内容。
    • 在 Base64 中序列化您的 String

    public class SpecialCharacter
    {
        [XmlElement(ElementName = "special")]
        public String Base64
        {
            get
            {
                return Convert.ToBase64String(System.Text.Encoding.UTF32.GetBytes(special));
            }
            set
            {
                if (value == null)
                {
                    special = null;
                    return;
                }
    
                special = System.Text.Encoding.UTF32.GetString(Convert.FromBase64String(value));
            }
        }
    
        [XmlIgnore]
        public String special = Char.ConvertFromUtf32(0x05).ToString();
    }
    

    【讨论】:

    • 这并不能解决读取 xml 文件的问题。写入过程不会改变(xml文件是相同的)。也不清楚你的意思,因为写作时我必须使用XmlTextWriter 而不是XmlTextReader 或者我是否误会了什么。 Base64-String 是一个好主意,但我总是有很多文件存在这个问题,更重要的是我能够正确读取它们,而不是更改我的未来文件代码。我喜欢XmlIgnore 属性:)