Showing posts with label xml. Show all posts
Showing posts with label xml. Show all posts

Friday, 20 February 2009

To serialize, or not to serialize - that is the question

When serializing objects, you sometimes want to exclude properties that don't meet a certain criteria. This validation could be a simple check for default/null values or a more complicated scenario.

This example shows how to prevent a DateTime property being serialized if it hasn't been set, meaning it's value will be DateTime.MinValue. You'll notice there is the property for date of birth and a method called ShouldSerializeDateOfBirth that has no parameters and returns a boolean value. If this returns true, serialize, and vice versa. How does it get called I hear you ask. I don't actually know exactly but the key to invoking is in the name - make sure it starts with "ShouldSerialize" followed by the name of the property (in this case, "DateOfBirth").

public bool ShouldSerializeDateOfBirth() { return DateOfBirth != DateTime.MinValue; }

[XmlElement("dateofbirth")]
public DateTime DateOfBirth { get; set; }

Saturday, 7 June 2008

How do I remove whitespace from XML in C#.NET?

Once again... thanks Neil!

using System;
using System.Text.RegularExpressions;

public static class XMLUtility
{
public static string RemoveWhitespace( string xml )
{
Regex regex = new Regex(@">\s*<");
xml = regex.Replace(xml, "><");

return xml.Trim();
}
}

XML serialization in C#.NET

Have you ever tried to parse XML using the .NET framework? I have, and I can never remember the right/wrong way to do it. I normally spend hours on the internet before finding the same solution that I found during my previous attempt. Not anymore! Instead of interacting with the XML directly, convert it to an object that can be easily manipulated. This post shows how to deserialize an XML string into an object and serialize it back into an XML string using attributes from the System.Xml.Serialization namespace in the target class. The important ones that I've highlighted are XmlRoot, XmlAttribute and XmlElement. They're pretty self explanitory - they basically map a class to a root node, a class member to an attribute within a node and a class member to an element node respectively. When declaring these attributes, you specify the name of the attribute/node used in the string XML to establish the relationship. If your class uses exactly the same naming convention as the XML structure, you could (in theory) leave out these attributes. In most cases, the 2 naming conventions differ. I would recommend using them regardless because it makes your application more future proof. If the name of an element node changes, you only have to update the corresponding attribute instead of renaming a class member which could cause problems elsewhere (in the same or even other applications).

This example includes a utility class with 2 important methods - DeserializeObject and SerializeObject. Both use generics so you pass the target class when calling either method. The XML sample can be deserialized to create a Person object. Alternatively, an existing Person object can be serialized to create a similar XML structure.

Utility class:

using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

public class XMLSerializationUtility
{
public static T DeserializeObject<T>( Encoding encoding, string xml )
{
try
{
using (MemoryStream memoryStream = new MemoryStream( StringToByteArray( encoding, xml ) ) )
{
using ( XmlTextWriter xmlTextWriter = new XmlTextWriter( memoryStream, encoding ) )
{
XmlSerializer xmlSerializer = new XmlSerializer( typeof( T ) );

return (T)xmlSerializer.Deserialize( memoryStream );
}
}
}
catch
{
return default( T );
}
}

public static string SerializeObject<T>( Encoding encoding, T obj )
{
try
{
MemoryStream memoryStream = new MemoryStream();

using ( XmlTextWriter xmlTextWriter = new XmlTextWriter( memoryStream, encoding ) )
{
XmlSerializer xmlSerializer = new XmlSerializer( typeof( T ) );
xmlSerializer.Serialize( xmlTextWriter, obj );

memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
}

return ByteArrayToString( encoding, memoryStream.ToArray() );
}
catch
{
return string.Empty;
}
}

private static Byte[] StringToByteArray( Encoding encoding, string xml )
{
return encoding.GetBytes( xml );
}

private static string ByteArrayToString( Encoding encoding, byte[] byteArray )
{
return encoding.GetString( byteArray );
}
}

Person class:

using System;
using System.Xml.Serialization;

[XmlRoot( "person" ) ]
public class Person
{
private Guid _id;

[XmlAttribute( "id" )]
public Guid ID;
{
get { return _id; }
set { _id = value; }
}

private string _name;

[XmlElement( "Name" )]
public string Name;
{
get { return _name; }
set { _name = value; }
}

private DateTime _dateOfBirth;

[XmlElement( "dob" )]
public DateTime DateOfBirth;
{
get { return _dateOfBirth; }
set { _dateOfBirth = value; }
}

}

XML:

<?xml version="1.0" encoding="utf-8"?>
<person id="0ADD2974-B14E-440B-B435-C0AF65E57ACF">
<name>Andrew Gunn</name>
<dob>1985-08-08T12:00:00Z</dob>
</person>

Deserialize string XML into a Person object:
Person person = XMLSerializationUtility.DeserializeObject<Person>( Encoding.UTF8, xml );

Serialize a Person object into string XML:
string xml = XMLSerializationUtility.SerializeObject<Person>( Encoding.UTF8, Person );