I am trying to use XmlAttributeOverrides to control which class properties appear in the xml after the class has been serialized. It works on properties that are on the "root" class but not on nested properties. Here is a simple example to illustrate what I'm trying to accomplish.
My class hierarchy is as follows:
public class Main
{
public string Name { get; set; }
public Location Address { get; set; }
}
public class Location
{
public string StreetAddress { get; set; }
public Contact ContactInfo{ get; set; }
}
public class Contact
{
public string PhoneNumber { get; set; }
public string EmailAddr { get; set; }
}
When I serialize Main(), I get something like this:
<Main>
<Name></Name>
<Address>
<StreetAddress></StreetAddress>
<ContactInfo>
<PhoneNumber></PhoneNumber>
<EmailAddr></EmailAddr>
</ContactInfo>
</Address>
</Main>
What I am able to do is keep either Name or Address from appearing by using this:
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
XmlAttributes attribs = new XmlAttributes();
attribs.XmlIgnore = true;
attribs.XmlElements.Add(new XmlElementAttribute("Address"));
overrides.Add(typeof(Main), "Address", attribs);
xs = new XmlSerializer(typeof(Main), overrides);
What I need to also be able to do is keep Main.Address.ContactInfo from being serialized SOMETIMES (if it's empty). I tried the following but they didn't work:
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
XmlAttributes attribs = new XmlAttributes();
attribs.XmlIgnore = true;
attribs.XmlElements.Add(new XmlElementAttribute("ContactInfo "));
overrides.Add(typeof(Contact), "ContactInfo ", attribs);
xs = new XmlSerializer(typeof(Contact), overrides);
and...
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
XmlAttributes attribs = new XmlAttributes();
attribs.XmlIgnore = true;
attribs.XmlElements.Add(new XmlElementAttribute("ContactInfo "));
overrides.Add(typeof(Main.Address.ContactInfo), "ContactInfo ", attribs);
xs = new XmlSerializer(typeof(Main.Address.ContactInfo), overrides);
I've actually tried a lot more, including using XPath statements to designate the attribute name to target but didn't want to fill this page up with failed attempts. Is what I'm asking even possible by this method?
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
ifContactInfo
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: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 thexsi:*
andxsd:*
attributes from being output for your objects when they are serialized. Also, specify that the element is not nullable by using theSystem.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:With these changes to your
Location
class, the emptyContactInfo
property should no longer be serialized to XML when none of the properties are null, empty, or whitespace, or ifContactInfo
itself is null.You should make similar changes to your other objects.
See my other stackoverflow answers for more on .NET XML serialization:
For anyone else trying to do this with XmlAttributeOverrides, turns out that @user1437872 was very close to finding the answer. Here is the override code to ignore the nested element ContactInfo.