无法让XDocument/XmlWriter生成带缩进换行的XML文件(底层用XmlProvider)
问题:新增XML元素无法被XmlWriter格式化缩进
场景:XML文档通过F# XmlProvider(来自FSharp.Data)读取创建,随后通过底层XDocument操作,保存代码如下:
static void Save(XDocument doc, string filename) { var settings = new XmlWriterSettings() { Indent = true, // 启用缩进 IndentChars = " ", // 缩进使用4个空格 NewLineChars = "\r\n", // 换行符设置 NewLineHandling = NewLineHandling.Replace, // 替换默认换行符 Encoding = new UTF8Encoding(false) }; using (var writer = XmlWriter.Create(filename, settings)) { doc.Save(writer); } }
已确认代码生效(可通过开关UTF8 BOM验证),但生成的XML中新增的<ES_XMLXPATH>元素始终无换行和缩进,表现为:
<ES_XMLXPATH xp_ordernr="1" xp_xpath="ES_PUBLICATIONRECORD/ds_program" /><ES_XMLXPATH xp_ordernr="1" xp_xpath="ES_PUBLICATIONRECORD/ds_program/ES_PRODUCT/masterProgram" /><ES_XMLXPATH xp_ordernr="1" xp_xpath="ES_PUBLICATIONRECORD/ds_program/ES_PRODUCT/masterProgram/ES_PRODUCT/oid" />
文档中原有的从磁盘读取的内容格式正常,仅新增元素无法被格式化。
参考MS文档备注(翻译)
备注
此属性仅适用于输出文本内容的XmlWriter实例;否则将忽略此设置。
只要元素不包含混合内容,就会对元素进行缩进。一旦调用WriteString或WriteWhitespace方法写出混合元素内容,XmlWriter就会停止缩进。混合内容元素关闭后,缩进将恢复。
问题原因与解决方法
核心原因
你通过XDocument新增<ES_XMLXPATH>元素时,它们的父节点中存在零散的空白文本节点,导致XmlWriter判定该父节点为「混合内容」(元素+空白文本),从而停止对后续新增元素的缩进处理。
原磁盘读取内容格式正常,是因为XmlReader读取时保留了结构化的空白节点;而新增元素时若未清理父节点的无效空白,就会触发混合内容的判定逻辑。
解决方法
清理父节点的空白文本节点
在添加新元素前,移除父节点下所有无意义的空白文本:// 假设parentNode是要添加ES_XMLXPATH的父节点 parentNode.Nodes() .Where(n => n.NodeType == XmlNodeType.Text && string.IsNullOrWhiteSpace(((XText)n).Value)) .Remove();重新解析文档消除无效空白
将现有XDocument转换为字符串后重新解析,自动清理零散空白:var cleanDoc = XDocument.Parse(doc.ToString()); // 保存清理后的cleanDoc Save(cleanDoc, filename);
内容的提问来源于stack exchange,提问作者MrD at KookerellaLtd
相关产品推荐
相关产品推荐

