XmlDocument适合动态构建小到中等XML结构,需注意Save()调用、路径权限及自动转义;XDocument语法简洁、支持LINQ,推荐新项目;XmlWriter流式写入高性能低内存,适合大数据量;XmlSerializer适用于固定结构的对象序列化,但灵活性差。

用 XmlDocument 写入 XML:适合需要动态构建结构的场景
这是最传统、最可控的方式,适合你得边查边改、反复增删节点的情况。它把整个 XML 加载进内存树结构,写完再保存,所以对小到中等体积文件很稳妥。
常见错误是没调用 Save(),或者路径权限不足导致静默失败(尤其在 Windows 服务或 IIS 下)。注意:节点名和属性值里含 、<code>& 等字符时,XmlDocument 会自动转义,不用手动处理。
实操建议:
- 先用
new XmlDocument()创建空文档,再用CreateElement()和AppendChild()拼结构 - 如果要追加内容,先
Load()原文件,再定位到父节点插入新XmlElement - 保存前检查目标目录是否存在,用
Directory.CreateDirectory()预创建 - 避免在循环里反复
Load() → Modify → Save(),IO 开销大;应累积修改后一次性保存
用 XDocument(LINQ to XML)写入:语法简洁,推荐新项目首选
XDocument 是 .NET 3.5 起引入的现代 API,写法接近 JSON 构建逻辑,链式调用清晰,且原生支持 LINQ 查询。它不区分“元素”和“文档”类型,XElement 本身就能直接 Save()。
容易踩的坑是误用 ToString() —— 它默认输出带声明头的完整字符串,但如果你只是拼片段,要用 ToString(SaveOptions.OmitDuplicateNamespaces) 或直接 Save() 到文件流。
实操建议:
- 新建文档:
var doc = new XDocument(new XElement("Root", new XElement("Item", new XAttribute("id", "1"), "data"))) - 追加节点:用
doc.Root.Add(new XElement("Item", ...)),比XmlDocument少两步 - 写入时指定编码:用
doc.Save(new StreamWriter(path, false, Encoding.UTF8)),避免 BOM 或 ANSI 乱码 - 不要对同一个
XElement多次调用Add()同一个实例——会抛InvalidOperationException:“The node has already been added to a tree.”
用 XmlWriter 流式写入:高性能、低内存,适合大数据量导出
当你导出成千上万个订单、日志条目或配置项时,XmlWriter 是唯一合理选择。它不建内存树,而是按顺序“写一行丢一行”,峰值内存几乎恒定。
缺点是不能回退、不能随机修改——写错一个标签就得重来。另外,默认不缩进,调试时看着费劲;若需格式化,得设 XmlWriterSettings.Indent = true,但会轻微拖慢速度。
实操建议:
- 必须用
using包裹,否则可能锁住文件或丢失末尾结束标签 - 写属性优先用
WriteAttributeString(),比拼字符串安全;写文本内容用WriteString(),它会自动转义 - 别在
WriteStartElement()后直接WriteEndElement()——空元素应改用WriteElementString()或WriteFullEndElement() - 如需写 CDATA,用
WriteCData(),别手拼字符串
用序列化(XmlSerializer)写入:对象 ↔ XML 一键互转,但灵活性差
当你有一组强类型 C# 类,且 XML 结构基本固定(比如配置类、DTO),XmlSerializer 最省事。标几个 [XmlRoot]、[XmlElement] 就能直接 Serialize() 成文件。
但它对字段命名、继承、集合类型很敏感:私有字段默认不序列化;List<t></t> 会生成多个同名子元素,但数组可能被包一层;DateTime 默认输出 ISO 格式,无法自定义为“yyyy-MM-dd”。一旦需求变复杂(比如某些字段只读、某些条件输出),就得切回手动方式。
实操建议:
- 确保类有无参构造函数,否则反序列化会失败
- 用
XmlAttribute控制字段输出为属性而非子元素 - 避免序列化含循环引用的对象,会抛
InvalidOperationException - 若需控制命名,统一用
[XmlElement(ElementName = "user_id")],别依赖默认 PascalCase → camelCase 规则
写 XML 看似简单,真正上线后出问题的,八成卡在编码、路径权限、特殊字符转义、或并发写入冲突上。尤其是多线程环境下用 XmlDocument 或 XDocument 读写同一文件,没加锁必然丢数据。流式写入虽快,但异常中断时文件可能残缺——记得写前备份或写到临时文件再原子替换。


















