myWallJSON
myWallJSON

Reputation: 9502

How to exclude class fields from serialization by XmlElement name?

Say we have a class like:

using System;
using System.Xml.Serialization;

namespace XmlEntities {
    [XmlRoot("Agent")]
    public class RootClass {
        private string element_description;

        [XmlElement("Name")]
        public string Name{ get; set; }
        }

        [XmlElement("Surname")]
        public string Surname{ get; set; }
    }
}

And we want to serialize into xml only Name XmlElement. How to limit that at serialization?

Upvotes: 1

Views: 4218

Answers (2)

fcuesta
fcuesta

Reputation: 4520

If you want to ignore the element at runtime, at serialization, you can use XmlAttributeOverrides:

XmlAttributeOverrides overrides = new XmlAttributeOverrides();
XmlAttributes attribs = new XmlAttributes();
attribs.XmlIgnore = true;
attribs.XmlElements.Add(new XmlElementAttribute("Surname"));
overrides.Add(typeof(RootClass), "Surname", attribs);

XmlSerializer ser = new XmlSerializer(typeof(RootClass), overrides);
RootClass agent = new RootClass();
agent.Name = "Marc";
agent.Surname = "Jobs";
ser.Serialize(Console.Out, agent);

Upvotes: 3

Ben
Ben

Reputation: 6059

Have you encountered the [XmlIgnore] attribute? Adding it to members of your class will exclude them from serialization.

So, for example, you can replace [XmlElement("Surname")] with [XmlIgnore], and then your serialized agent will look like this:

<Agent>
    <Name>John Doe</Name>
</Agent>

Alternately, if all you really want is just <Name>John Doe</Name>, you could write a wrapper class:

[XmlRoot("Name")]
public class NameElement
{
    [XmlText]
    public string Name { get; set; }
}

* EDIT *

While it's possible to generate such wrappers at runtime, it's difficult, inefficient, and not very practical.

To do so, I guess you could reflectively examine your object and find the properties you want (root.GetType().GetProperties().Where(p => /* your logic here */)), and use System.Reflection.Emit to generate the appropriate class. While possible, it's not reasonable - it'd be a huge amount of code relative to your actual logic, and you could easily destabilize the runtime and/or leak memory.

A better way to achieve the dynamicism you want is to forego System.Xml.Serialization and use System.Xml.Linq. This would require you to write code that built up the xml yourself, but it's super easy:

public XElement ConvertToXml(RootClass root)
{
    return new XElement("Name", root.Name);
}

You can write an XElement to any stream using the element.Save(Stream) instance method on XElement.

Read more about Linq to XML at MSDN

Upvotes: 6

Related Questions