Applies To: .NET (C#, VB.NET)
If you do much work with XML in either VB.NET or C# you’re probably looking for a way to control it’s formatting and make it look “pretty”. This has come up a few times for me so I thought I’d share a quick method for doing this.
Most often I’m using this to format XML from Web Services (Mostly SharePoint) or to take a look at XML I’ve generated for Web Services to see what’s wrong. But for this example, I’ve got a couple of helper functions that generate some XML using objects from the System.Xml namespace. Here’s how I generate the XML used here:
Private Function GetXML() As String Dim doc As New XmlDocument Dim rn As XmlNode = doc.CreateElement("TMNT") Dim sn As XmlNode = doc.CreateElement("Turtles") sn.AppendChild(CreateTurtleNode(doc, "Leonardo", "Blue", "Katana")) sn.AppendChild(CreateTurtleNode(doc, "Raphael", "Red", "Sai")) sn.AppendChild(CreateTurtleNode(doc, "Michelangelo", "Orange", "Nunchaku")) sn.AppendChild(CreateTurtleNode(doc, "Donatello", "Purple", "Bo")) rn.AppendChild(sn) doc.AppendChild(rn) Return doc.InnerXml End Function Private Function CreateTurtleNode(doc As XmlDocument, Name As String, Color As String, Weapon As String) As XmlNode Dim tn As XmlNode = doc.CreateElement("Turtle") Dim na As XmlAttribute = doc.CreateAttribute("Name") na.Value = Name tn.Attributes.Append(na) Dim ca As XmlAttribute = doc.CreateAttribute("Color") ca.Value = Color tn.Attributes.Append(ca) Dim wa As XmlAttribute = doc.CreateAttribute("Weapon") wa.Value = Weapon tn.Attributes.Append(wa) Return tn End Function
This is just sample code to get some unformatted XML and if you display the results of the GetXML function, here’s what you get:
<TMNT><Turtles><Turtle Name=”Leonardo” Color=”Blue” Weapon=”Katana” /><Turtle Name=”Raphael” Color=”Red” Weapon=”Sai” /><Turtle Name=”Michelangelo” Color=”Orange” Weapon=”Nunchaku” /><Turtle Name=”Donatello” Color=”Purple” Weapon=”Bo” /></Turtles></TMNT>
This isn’t terrible and if you’re just using this in your code, no worries! But if you want to display this to an end user or even yourself, proper lines and indentation can make a huge difference – especially since your XML is almost guaranteed to be more complex than my example above.
There are some crazy examples out there of reading through the string and manually inserting line returns and spaces when detecting the less than or greater than symbols. These are usually error prone and won’t take into account all the various possibilities for XML. They’re inefficient, ugly, and lame. Fortunately, there are some helpful objects in the System.IO namespace and the System.Xml namespace that make all of this very easy. Here’s the function:
Private Function PrettyXML(XMLString As String) As String Dim sw As New StringWriter() Dim xw As New XmlTextWriter(sw) xw.Formatting = Formatting.Indented xw.Indentation = 4 Dim doc As New XmlDocument doc.LoadXml(XMLString) doc.Save(xw) Return sw.ToString() End Function
I imagine this could be improved (feel free to share in the comments), but it definitely does the job. The key elements are the XmlTextWriter’s properties Formatting and Indentation. There are several other properties and methods you can use to customize even further, but the above produces a fairly nice result:
<?xml version="1.0" encoding="utf-16"?> <TMNT> <Turtles> <Turtle Name="Leonardo" Color="Blue" Weapon="Katana" /> <Turtle Name="Raphael" Color="Red" Weapon="Sai" /> <Turtle Name="Michelangelo" Color="Orange" Weapon="Nunchaku" /> <Turtle Name="Donatello" Color="Purple" Weapon="Bo" /> </Turtles> </TMNT>
Now all the lines and indentation are there as expected! We even get the nice XML Declaration free of charge.