xmldocument读写小到中等xml最稳,大文件或只读场景须用xmlreader/xmlwriter,对象序列化优先xmlserializer;加载前需检查文件存在性并异常处理,保存必须调用save(),中文乱码需指定utf-8编码,xmltextreader已过时应改用xmlreader.create配合httpclient异步流,反序列化失败常因访问修饰符、无参构造函数、命名空间或可空类型配置缺失。

直接用 XmlDocument 读写小到中等规模的 XML 配置文件最稳;遇到大文件或只读场景,必须换 XmlReader / XmlWriter;序列化对象优先走 XmlSerializer,别手撸节点。
用 XmlDocument 加载并修改配置文件时,为什么总报“根元素缺失”?
常见错误是调用 doc.Load("config.xml") 前文件不存在,而你没处理异常或初始化空文档。它不会自动创建文件,也不会帮你补声明头。
- 加载前先检查文件是否存在:
File.Exists("config.xml"),不存在就用doc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?><appconfig></appconfig>")初始化 - 保存前务必调用
doc.Save("config.xml"),否则所有修改只在内存里 - 如果写入中文内容但保存后乱码,说明没指定编码:用
XmlTextWriter替代默认保存,或手动设置doc.XmlResolver = null防止外部 DTD 加载干扰
从 URL 读取 XML(比如接口返回)时,XmlTextReader 已过时,该用什么?
XmlTextReader 在 .NET Core/.NET 5+ 中已被标记为 obsolete,继续用会触发编译警告,且不支持异步 —— 实际项目中容易卡主线程。
- 替代方案是
XmlReader.Create(new HttpClient().GetStreamAsync(url).Result),但注意:`.Result` 有死锁风险,应改用await+XmlReader.Create(stream) - 更推荐组合
HttpClient+XmlSerializer:先await client.GetStringAsync(url)拿到字符串,再用XmlSerializer.Deserialize(new StringReader(xmlStr)) - 若 XML 来自不可信源,必须设
XmlReaderSettings.DtdProcessing = DtdProcessing.Prohibit,否则可能触发 XXE 攻击
XmlSerializer 反序列化失败,常见原因有哪些?
不是类结构和 XML 标签对不上那么简单 —— 字段访问修饰符、默认构造函数、命名空间、空值处理都可能让 Deserialize 直接抛 InvalidOperationException。
- 目标类所有需映射的字段/属性必须是
public,且类本身要有无参构造函数 - 如果 XML 有命名空间(如
xmlns="http://tempuri.org/"),必须在XmlSerializer构造时传入new XmlRootAttribute { Namespace = "http://tempuri.org/" } - 含可空类型(如
int?)时,XML 中对应节点为空或缺失,需加[XmlElement(IsNullable = true)],否则反序列化直接失败 - 别忽略
XmlSerializer.UnknownElement事件 —— 它能帮你快速定位字段名大小写或拼写不一致的问题
生成 XML 时,用 XmlWriter 还是拼字符串?
拼字符串看似简单,但一碰属性转义(比如 value="a & b")、编码、缩进、声明头,立刻出问题。而 XmlWriter 是唯一能保证格式合法、安全输出的内置方式。
- 永远用
XmlWriter.Create(stream, new XmlWriterSettings { Indent = true, Encoding = Encoding.UTF8 }),别用默认设置 —— 默认不缩进、不声明编码,人眼难读 - 写属性前必须先写开始标签:
WriteStartElement("book")→WriteAttributeString("id", "101")→WriteString("C#入门")→WriteEndElement() - 如果要写 CDATA 段(比如嵌入 JS 或 HTML 片段),必须用
WriteCData("..."),不能靠字符串替换
真正麻烦的从来不是“怎么写出来”,而是“怎么确保每次读出来的数据结构不变”——尤其是当 XML 来自第三方服务或旧系统时,一个没声明的命名空间、一行多余注释、甚至 BOM 头,都可能让 XmlDocument.SelectSingleNode 返回 null 而不报错。动手前先用 XmlReader 扫一遍结构,比硬调十分钟 XPath 更省时间。











