It is possible to pretty-print an XML string via a streaming transformation with XmlWriter.WriteNode(XmlReader, true). This method
copies everything from the reader to the writer and moves the reader to the start of the next sibling.
Define the following extension methods:
public static class XmlExtensions
{
public static string FormatXml(this string xml,
bool indent = true, bool newLineOnAttributes = false, string indentChars = " ",
ConformanceLevel conformanceLevel = ConformanceLevel.Document, bool ignoreWhitespace = true) =>
// By default we ignore the incoming whitespace, since the purpose of this method is to reformat the incoming xml.
xml.FormatXml( new XmlWriterSettings { Indent = indent, NewLineOnAttributes = newLineOnAttributes, IndentChars = indentChars, ConformanceLevel = conformanceLevel },
new XmlReaderSettings { ConformanceLevel = conformanceLevel, IgnoreWhitespace = ignoreWhitespace });
public static string FormatXml(this string xml, XmlWriterSettings writerSettings, XmlReaderSettings? readerSettings = default)
{
using (var textReader = new StringReader(xml))
using (var xmlReader = XmlReader.Create(textReader, readerSettings ))
using (var textWriter = new StringWriter())
{
using (var xmlWriter = XmlWriter.Create(textWriter, writerSettings))
xmlWriter.WriteNode(xmlReader, true);
return textWriter.ToString();
}
}
}
And now you will be able to do:
var inXml = @"<?xml version='1.0'?><response><error code='1'> Success</error></response>";
var newXml = inXml.FormatXml(indentChars : "", newLineOnAttributes : false); // Or true, if you prefer
Console.WriteLine(newXml);
Which prints
<?xml version='1.0'?>
<response>
<error code="1"> Success</error>
</response>
Notes:
Other answers load the XML into some Document Object Model such as XmlDocument or XDocument/XElement, then re-serialize the DOM with indentation enabled.
This streaming solution completely avoids the added memory overhead of a DOM.
In your question you do not add any indentation for the nested <error code='1'> Success</error> node, so I set indentChars : "". Generally an indentation of two spaces per level of nesting is customary.
Attribute delimiters will be unconditionally transformed to double-quotes if currently single-quotes. (I believe this is true of other answers as well.)
Passing conformanceLevel : ConformanceLevel.Fragment allows strings containing sequences of XML fragments to be formatted.
Other than ConformanceLevel.Fragment, the input XML string must be well-formed. If it is not, XmlReader will throw an exception.
Demo fiddle here.
XmlDocumentwhich would disqualify the highest voted answer on this question.