C#怎么把XDocument或XmlDocument转为string

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

XDocument.ToString() 会丢失格式,别直接用

很多人看到 XDocumentToString() 方法就直接调,结果发现输出是紧凑格式(没换行、没缩进),甚至某些节点顺序异常。这是因为它的默认 ToString() 实际调用的是 Save(TextWriter) 的简化路径,不走格式化逻辑。

  • 正确做法是用 Save(StringBuilder, SaveOptions) 配合 SaveOptions.None(保留空格)或 SaveOptions.DisableFormatting(强制紧凑)
  • 如果要带缩进,必须显式用 XmlWriter 并设置 Indent = true
  • ToString()XmlDocument 更不可靠——它只返回根元素内部的 XML 片段,不包含声明和完整结构

推荐:用 StringWriter + XmlWriterXDocument

这是最可控、兼容性最好的方式,能精确控制编码、缩进、是否写 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 必须用 OuterXmlSave

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" 已足够。