XmlWriter inserts spaces when xml: space = preserve

Given this code (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); 

The statement fails because XmlWriter inserts a new line and indentation around the <item> elements, which seemingly contradict the xml:space="preserve" attribute.

I am trying to accept input without spaces (or only significant spaces and already loaded in the XmlDocument ) and pretty print it without adding any spaces inside the elements marked for saving spaces (for obvious reasons).

Is this a mistake or am I doing something wrong? Is there a better way to achieve what I'm trying to do?

Change I have to add that I need to use XmlWriter with Indent=true on the output side. In "real" code, this is passed outside of my code.

+4
source share
1 answer

Ok, I found a workaround.

It turns out that XmlWriter doing the right thing if there really are any spaces in the xml:space="preserve" block xml:space="preserve" - it’s only when there is no one to screw it and add some, And it’s convenient if there are some white nodes, even if they are empty. So the trick I came up with is to decorate the document with extra spaces of length 0 in the appropriate places before trying to write it down. The result is exactly what I want: to print fairly widely everywhere, except when the space value is significant.

The workaround is to change the indoor unit to:

 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); } } } 

I still think this XmlWriter behavior is a bug.

+4
source

All Articles