There are easier ways to achieve what you're looking for.
You said that what you are trying to achieve is to not serialize /Main/Address/ContactInfo
if ContactInfo
contains no data.
If you leave your code as is, it will serialize all of Main's properties, whether they are null or empty or not. The first step, is you need to add a XmlSerializerNamespaces
property to all of your objects or each empty object will be serialized as <myElement xsi:nil="true" />
. This can be accomplished easily, as follows:
public MyXmlElement
{
public MyXmlElement()
{
// Add your own default namespace to your type to prevet xsi:* and xsd:*
// attributes from being generated.
this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {
new XmlQualifiedName(string.Empty, "urn:myDefaultNamespace") });
}
[XmlElement("MyNullableProperty", IsNullable=false)]
public string MyNullableProperty
{
get
{
return string.IsNullOrWhiteSpace(this._myNullableProperty) ?
null : this._myNullableProperty;
}
set { this._myNullableProperty = value; }
}
[XmlNamespacesDeclaration]
public XmlSerializerNamespaces Namespaces { get { return this._namespaces; } }
private XmlSerializerNamespaces _namespaces;
}
The code above declares a Namespaces
property that holds all the relevant namespaces for the XML object. You should provide a default namespace for all of your objects (modeled after the code above). This prevents the xsi:*
and xsd:*
attributes from being output for your objects when they are serialized. Also, specify that the element is not nullable by using the System.Xml.Serialization.XmlElementAttribute
.
Furthermore, by checking for string.IsNullOrWhiteSpace(someVariable)
and returning null, then the
property will not be serialized when the above has been done.
So, putting this all together for your Location
class:
public class Location
{
// You should have a public default constructor on all types for (de)sereialization.
public Location()
{
this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {
new XmlQualifiedName(string.Empty, "urn:myNamespace"); // Default namespace -- prevents xsi:nil="true" from being generated, as well as xsd:* attributes.
});
}
public string StreetAddress
{
// If you don't want <StreetAddress xsi:nil="true" /> to be generated, do this:
get { return string.IsNullOrEmpty(this._streetAddress) ? null : this._streetAddress; }
// Otherwise, if you don't care, just do
// get;
// Only need to implement setter if you don't want xsi:nil="true" to be generated.
set { this._streetAddress = value; }
// Otherwise, just
// set;
}
private string _streetAddress;
[XmlElement("ContactInfo", IsNullable=false)]
public Contact ContactInfo
{
// You must definitely do this to prevent the output of ContactInfo element
// when it's null (i.e. contains no data)
get
{
if (this._contactInfo != null && string.IsNullOrWhiteSpace(this._contactInfo.PhoneNumber) && string.IsNullOrWhiteSpace(this._contactInfo.EmailAddr))
return null;
return this._contactInfo;
}
set { this._contactInfo = value; }
}
private Contact _contactInfo;
[XmlNamespacesDeclarations]
public XmlSerializerNamespaces Namespaces
{
get { return this._namespaces; }
}
private XmlSerializerNamespaces _namespaces;
}
With these changes to your Location
class, the empty ContactInfo
property should no longer be serialized to XML when none of the properties are null, empty, or whitespace, or if ContactInfo
itself is null.
You should make similar changes to your other objects.
See my other stackoverflow answers for more on .NET XML serialization: