Put Down the XmlNode and Step Away From the StringBuilder
Posted: 2/12/2008 2:29:33 PM
I'm sure there are plenty of you out there who have your boss hankering
to use some of that "Xml Stuff". Sometimes we get sheltered in our own
little world and haven't actually had to work with a whole lot of xml
data that wasn't already wrapped up by the Project Settings object
created by Visual Studio. So naturally, you'd probably go to the "
tubes"
and search for some additional information. Undoubtedly, you will run
across pages telling you how to construct some Xml in C# by creating a
new XmlDocument and adding XmlNode children which will have attributes
and subnodes and namespaces, ad infinitum. And you'll realize you now have
some of the world's fugliest code. So you decide, "oh, well xml is
really similar to html, I'll just build it using a StringBuilder" and
you end up with slightly less fugly code, that is until you try to read
it back in.
These
methods are completely unnecessary. PUT DOWN THE XMLNODE AND STEP AWAY
FROM THE STRINGBUILDER. Slowly move your hand to the mouse and scroll
down to read about the easiest way to write
and read Xml in the .net framework.
Ok,
quick show of hands: who thinks working with simple .net business model
objects is brain dead easy? Alright, if your hand isn't up, you are
beyond hope, please leave now. Of course, working with simple objects
is about the simplest exercise for code next to "Hello World". If you
can create a .net object that models the xml you want to store, you are 95% done with outputting well formed Xml.
Example: If I wanted to store information about a few people and their pets I would create three classes:
public class PetClub
{
public List<Person> Members { get; set; }
}
public class Person
{
public string Name { get; set; }
public List<Pet> Pets { get; set; }
}
public class Pet
{
public string Name { get; set; }
public string Type { get; set; }
}
To
get an Xml representation of an instance of PetClub, all you have to do
is use the XmlSerializer found in the System.Xml.Serialization
namespace. I've wrapped up all the necessary code into a short utility
method.
public static string ConvertToXml(object item)
{
XmlSerializer xmlser = new XmlSerializer(item.GetType());
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
xmlser.Serialize(ms, item);
UTF8Encoding textconverter = new UTF8Encoding();
return textconverter.GetString(ms.ToArray());
}
}
Simply calling: ConvertToXml(myPetClubInstance) will spit back the following xml:
<PetClub xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Members>
<Person>
<Name>Jon</Name>
<Pets>
<Pet>
<Name>Chester</Name>
<Type>Savannah Cat</Type>
</Pet>
<Pet>
<Name>Abby</Name>
<Type>Domestic Miniature Panther</Type>
</Pet>
</Pets>
</Person>
<Person>
<Name>Dan</Name>
<Pets>
<Pet>
<Name>Lucy</Name>
<Type>Semi-sweet Chocolate Lab</Type>
</Pet>
</Pets>
</Person>
</Members>
</PetClub>
At this point you might be saying: "That is cool and all, Jon, but this
looks like a lot of xml to be outputting for such little actual data.
And what if I want to have more control over xml element naming". Dear
friend, let not your heart be troubled for there is help on the way. By
adding some simple Property Attributes to our classes we can completely
change how our xml is constructed. We can have the object in whatever
form is most convienient for our program while still allowing us to
interoperate with an xml document created by a different application
with a different idea of what good names are.
Changing our two classes to:
public class Person
{
[XmlElement("FirstName")]
public string Name { get; set; }
public List<Pet> Pets { get; set; }
}
public class Pet
{
[XmlAttribute("Name")]
public string Name { get; set; }
[XmlAttribute("Breed")]
public string Type { get; set; }
}
Will output this xml:
<PetClub xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Members>
<Person>
<FirstName>Jon</FirstName>
<Pets>
<Pet Name="Chester" Breed="Savannah Cat" />
<Pet Name="Abby" Breed="Domestic Miniature Panther" />
</Pets>
</Person>
<Person>
<FirstName>Dan</FirstName>
<Pets>
<Pet Name="Lucy" Breed="Semi-sweet Chocolate Lab" />
</Pets>
</Person>
</Members>
</PetClub>
Pretty simple, huh? Can you imagine how difficult it would be to
make these changes via XmlNodes or a StringBuilder? There are about 10
other property attributes available for xml
serialization, including the very useful XmlIgnore() attribute which
makes the appropriate property not serialized. I'll leave the rest of
the research up to you.
And I almost forgot, to read your xml back into an object use the following method:
public static T FromXml<T>(string xml)
{
XmlSerializer xmlser = new XmlSerializer(typeof(T));
using (System.IO.StringReader sr = new System.IO.StringReader(xml))
{
return (T)xmlser.Deserialize(sr);
}
}
Sample Code -
XmlSerializerSample.cs (2.33 KB)
Tags: Tips and Tricks