What is the simplest way to get indented XML with line breaks from XmlDocument?
Based on the other answers, I looked into XmlTextWriter
and came up with the following helper method:
static public string Beautify(this XmlDocument doc)
{
StringBuilder sb = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings
{
Indent = true,
IndentChars = " ",
NewLineChars = "\r\n",
NewLineHandling = NewLineHandling.Replace
};
using (XmlWriter writer = XmlWriter.Create(sb, settings)) {
doc.Save(writer);
}
return sb.ToString();
}
It's a bit more code than I hoped for, but it works just peachy.
Adding line breaks and indents to XmlDocument
I have figured it out. XmlDocument should be written to a Stream with XmlWriter using, like Pavel suggested, XmlWriterSettings with Indent property enabled. Like this:
XmlDocument^ xmlDocument = gcnew XmlDocument();
xmlDocument->PreserveWhitespace = true;
//add some elements
XmlWriterSettings settings = new XmlWriterSettings();
XmlWriterSettings.Indent = true;
XmlWriterSettings.IndentChars = "\t"; //tabs instead of spaces
Stream^ stream = gcnew MemoryStream(); //or FileStream to write an Xml file directly to disk
XmlWriter^ writer = XmlWriter::Create(stream, settings);
xmlDocument->WriteTo(writer);
writer->Close();
Is there any way to save an XmlDocument *without* indentation and line returns?
Try this code:
XmlDocument doc = new XmlDocument();
using(XmlTextWriter wr = new XmlTextWriter(fileName, Encoding.UTF8))
{
wr.Formatting = Formatting.None; // here's the trick !
doc.Save(wr);
}
Format XML string to print friendly XML string
You will have to parse the content somehow ... I find using LINQ the most easy way to do it. Again, it all depends on your exact scenario. Here's a working example using LINQ to format an input XML string.
string FormatXml(string xml)
{
try
{
XDocument doc = XDocument.Parse(xml);
return doc.ToString();
}
catch (Exception)
{
// Handle and throw if fatal exception here; don't just ignore them
return xml;
}
}
[using statements are ommitted for brevity]
XDocument adds carriage return when generating final xml string
XNode.ToString
is a convenience that uses an XmlWriter
under the covers - you can see the code in the reference source.
Per the documentation for XmlWriterSettings.NewLineHandling
:
The Replace setting tells the XmlWriter to replace new line characters with \r\n, which is the new line format used by the Microsoft Windows operating system. This helps to ensure that the file can be correctly displayed by the Notepad or Microsoft Word applications. This setting also replaces new lines in attributes with character entities to preserve the characters. This is the default value.
So this is why you're seeing this when you convert your element back to a string. If you want to change this behaviour, you'll have to create your own XmlWriter
with your own XmlWriterSettings
:
var settings = new XmlWriterSettings
{
OmitXmlDeclaration = true,
NewLineHandling = NewLineHandling.None
};
string xmlString;
using (var sw = new StringWriter())
{
using (var xw = XmlWriter.Create(sw, settings))
{
doc.Root.WriteTo(xw);
}
xmlString = sw.ToString();
}
Force XmlDocument to save empty elements with an explicit closing tag
Here are three ways to force XmlDocument.Save to output a separate end tag for an empty XmlElement instead of an empty, self-closing tag.
Method 1
Insert an empty whitespace node inside the element:
UsersNode.AppendChild(Settings.CreateWhitespace(""));
Here's the output:
<Users FileDirectory="C:\data"></Users>
Method 2
Set the XmlElement.IsEmpty property of the element to false:
((XmlElement)UsersNode).IsEmpty = false;
Note that with this method, the default XML formatting settings will insert a line break between the start tag and the end tag. Here's the output:
<Users FileDirectory="C:\data">
</Users>
Method 3
Derive a custom XmlTextWriter that forwards all WriteEndElement calls to WriteFullEndElement:
public class CustomXmlTextWriter : XmlTextWriter
{
public CustomXmlTextWriter(string fileName)
: base(fileName, Encoding.UTF8)
{
this.Formatting = Formatting.Indented;
}
public override void WriteEndElement()
{
this.WriteFullEndElement();
}
}
Usage:
using (var writer = new CustomXmlTextWriter(Path.Combine(PathName, FileName)))
{
Settings.Save(writer);
}
This method might require less code overall if you have a lot of empty elements in your document.
As with Method 2, the default XML formatting settings will insert a line break between the start tag and end tag of each empty element.
Indentation and new line command for XMLwriter in C#
Use a XmlTextWriter
instead of XmlWriter
and then set the Indentation
properties.
Example
string filename = "MyFile.xml";
using (FileStream fileStream = new FileStream(filename, FileMode.Create))
using (StreamWriter sw = new StreamWriter(fileStream))
using (XmlTextWriter xmlWriter = new XmlTextWriter(sw))
{
xmlWriter.Formatting = Formatting.Indented;
xmlWriter.Indentation = 4;
// ... Write elements
}
Following @jumbo comment, this could also be implemented like in .NET 2.
var filename = "MyFile.xml";
var settings = new XmlWriterSettings()
{
Indent = true,
IndentChars = " "
}
using (var w = XmlWriter.Create(filename, settings))
{
// ... Write elements
}
Related Topics
Benchmarking Small Code Samples in C#, Can This Implementation Be Improved
Asp.Net: Invalid Postback or Callback Argument
Calling JavaScript Function from Codebehind
How to Get the Computer Name in .Net
Why Are Unsigned Int's Not Cls Compliant
How to Fix a Opacity Bug with Drawtobitmap on Webbrowser Control
How to Do Appbar Docking (To Screen Edge, Like Winamp) in Wpf
Difference Between Forward Slash (/) and Backslash (\) in File Path
Write File from Assembly Resource Stream to Disk
Convert Any Object to a Byte[]
Usercontrol' Constructor with Parameters in C#
How to Check If a String Contains Any of Some Strings
Entity Framework Core 2.0.1 Eager Loading on All Nested Related Entities