XDocument.ToString()会丢失格式,应使用XmlWriter配合XmlWriterSettings设置Indent=true来生成带缩进的XML字符串;XmlDocument需用OuterXml或XmlWriter.Save确保完整性和格式化。

用 XDocument.ToString() 会丢失格式,别直接用
很多人看到 XDocument 有 ToString() 方法就直接调,结果发现输出是紧凑格式(没换行、没缩进),甚至某些节点顺序异常。这是因为它的默认 ToString() 实际调用的是 Save(TextWriter) 的简化路径,不走格式化逻辑。
- 正确做法是用
Save(StringBuilder, SaveOptions)配合SaveOptions.None(保留空格)或SaveOptions.DisableFormatting(强制紧凑) - 如果要带缩进,必须显式用
XmlWriter并设置Indent = true -
ToString()对XmlDocument更不可靠——它只返回根元素内部的 XML 片段,不包含声明和完整结构
推荐:用 StringWriter + XmlWriter 转 XDocument
这是最可控、兼容性最好的方式,能精确控制编码、缩进、是否写 XML 声明等。
var doc = new XDocument(
new XElement("root",
new XElement("child", "text")
)
);
var settings = new XmlWriterSettings
{
Indent = true,
OmitXmlDeclaration = false,
Encoding = Encoding.UTF8
};
var sb = new StringBuilder();
using (var writer = XmlWriter.Create(sb, settings))
{
doc.Save(writer);
}
string xmlString = sb.ToString(); // 包含 声明和缩进
转 XmlDocument 必须用 OuterXml 或 Save
XmlDocument 没有类似 XDocument.Save() 的便捷方法,直接访问 InnerXml 会丢掉根节点外层标签;用 OuterXml 是最简方案,但不控制缩进;需要格式化就得走 Save(XmlWriter)。
-
doc.DocumentElement.OuterXml:只取根元素及其子树,不含 XML 声明 -
doc.OuterXml:包含整个文档内容,但依然没声明(除非你手动加了XmlDeclaration) - 真正完整且可格式化的写法,还是得用
XmlWriter,和XDocument一致
注意编码和 BOM 问题
生成的字符串本身是 string(UTF-16),但如果你后续要写入文件或 HTTP 响应,Encoding.UTF8 设置只影响 XmlWriter 写入字节流时的行为;若用 StringBuilder 接收,最终 ToString() 出来的仍是 .NET 字符串,BOM 不会自动出现。需要 BOM?得用 MemoryStream + StreamWriter 显式写入。
常见坑:把带 UTF-8 BOM 的字符串再用 UTF-8 编码一次,导致双重 BOM 或乱码。判断是否需要 BOM,看下游系统要求——多数现代解析器不需要,XML 声明里的 encoding="utf-8" 已足够。










