当xml:space = preserve时,XmlWriter插入空格

时间:2011-08-10 07:54:52

标签: c# .net xml whitespace xmlwriter

鉴于此代码(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中)而且非常打印而不用在标记为保留的元素中添加任何空格空白(原因很明显)。

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

修改:我应该补充一点,我必须在输出端使用XmlWriterIndent=true。在“真实”代码中,这是从我的代码外部传递的。

1 个答案:

答案 0 :(得分:4)

好的,我找到了解决方法。

事实证明,如果<{>} <{1}}块中的任何空格,XmlWriter会做正确的事情 - 只有当它没有任何螺丝时才会这样做起来并增加一些。并且方便地,如果存在一些空白节点,即使它们是空的,这也可以工作。所以我提出的技巧是在尝试写出之前在适当的位置用额外的0长度空格来装饰文档。结果正是我想要的:除了空白很重要之外,所有地方都可以打印。

解决方法是将内部块更改为:

xml:space="preserve"

...

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); } } } 的这种行为是一个错误。