XmlWriter在xml:space=preserve时插入空格

本文关键字:preserve 插入 空格 space xml XmlWriter | 更新日期: 2023-09-27 18:05:19

给定此代码(c#, .NET 3.5 SP1):

var doc = new XmlDocument();
doc.LoadXml("<?xml version='"1.0'"?><root>"
    + "<value xml:space='"preserve'">"
    + "<item>content</item>"
    + "<item>content</item>"
    + "</value></root>");
var text = new StringWriter();
var settings = new XmlWriterSettings() { Indent = true, CloseOutput = true };
using (var writer = XmlWriter.Create(text, settings))
{
    doc.DocumentElement.WriteTo(writer);
}
var xml = text.GetStringBuilder().ToString();
Assert.AreEqual("<?xml version='"1.0'" encoding='"utf-16'"?>'r'n<root>'r'n"
    + "  <value xml:space='"preserve'"><item>content</item>"
    + "<item>content</item></value>'r'n</root>", xml);

断言失败,因为XmlWriter<item>元素周围插入换行符和缩进,这似乎与xml:space="preserve"属性相矛盾。

我试图输入没有空白(或只有重要的空白,并且已经加载到XmlDocument)和漂亮的打印它没有添加任何空白的元素内标记保留空白(出于明显的原因)。

这是一个bug还是我做错了什么?有没有更好的方法来实现我想要做的事情?

编辑:我应该补充说,我必须在输出端使用XmlWriterIndent=true。在"实际"代码中,这是从我的代码外部传入的。

XmlWriter在xml:space=preserve时插入空格

好的,我找到了一个解决办法。

事实证明,如果在xml:space="preserve"块中实际上有任何空白,XmlWriter会做正确的事情——只有当没有任何空白时,它才会搞砸并添加一些。方便的是,如果有一些空白节点,即使它们是空的,这也有效。因此,我想出的技巧是在尝试将文档写出来之前,在适当的位置使用额外的0长度的空白来装饰文档。结果正是我想要的:除了空格重要的地方外,到处都打印得很漂亮。

解决方法是将内部块更改为:
PreserveWhitespace(doc.DocumentElement);
doc.DocumentElement.WriteTo(writer);

private static void PreserveWhitespace(XmlElement root)
{
    var nsmgr = new XmlNamespaceManager(root.OwnerDocument.NameTable);
    foreach (var element in root.SelectNodes("//*[@xml:space='preserve']", nsmgr)
        .OfType<XmlElement>())
    {
        if (element.HasChildNodes && !(element.FirstChild is XmlSignificantWhitespace))
        {
            var whitespace = element.OwnerDocument.CreateSignificantWhitespace("");
            element.InsertBefore(whitespace, element.FirstChild);
        }
    }
}

我仍然认为XmlWriter的这种行为是一个错误,虽然。