Search code examples
c#xmlserializationdata-mapping

Remapping a single tag while deserializing


I've refactored code like this:

public string CamelCASE { get; set; }

to:

public string CamelCase {get; set; }

only do discover that the input XML contains the former casing (let's call it a shouting camel). I have no control over how the XML document is produced. Nor do I burn of desire to retract my changes.

I'd like to map the loud camel property to a softly speaking one.

I've tried XmlElement and XmlMapping but to no greater success. A googling gave me only hits on how to map stuff to attributes, along lines of this post. However, I need only something like <LoudCAMEL> to be deserialized to a property public string QuietCamel.

Is there a smooth way to do so?

Edit

After adding the attribute as follows:

using System.Collections.Generic;
using System.Xml;

public class Beep : SuperBeep
{
  private readonly BeepType _a;

  public Beep() { _a = BeepType.SomeSome; }
  public Beep(BeepType input) { _a = input; }
  ~Beep() { }
  public override void Dispose() { }

  public BeepType Aaa { get { return _a; } }

  [XmlElement("CamelCASE")]
  public bool CamelCase { get; set; }
}

I can see the red, wavy highlight telling me Cannot access constructor 'XmlElement' here due its protection level. When I compile, though, I get the IDE crying out loud that 'System.Xml.XmlElement' is not an attribute class.

Frankly, I'm a bit confused by the suggestion to use attributes (this is targeting .NET 2.0), since I was under the impression that attributing wasn't available to .NET prior to version 3.5. Am I mistaken?


Solution

  • [XmlElement("CamelCASE")]
    public string CamelCase { get; set; }
    

    should be all you need, if you are keeping the shouty name in the xml. If you want to use the quieter name in new xml, but allow the old name to still work, it gets more complicated. You could use:

    public string CamelCase { get; set; }
    
    [XmlElement("CamelCASE"), Browsable(false)]
    [EditorBrowsable(EditorBrowsableState.Never)]
    public string CamelCaseLegacy {
        get { return CamelCase; }
        set { CamelCase = value; }
    }
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    public bool ShouldSerializeCamelCaseLegacy() { return false; }
    

    When serializing, the CamelCase property will serialize to <CamelCase>, and the CamelCaseLegacy element will be ignored due to the ShouldSerialize* method. However, when deserializing, the CamelCaseLegacy property will be used whenever <CamelCASE> is seen. We then map this value back to the CamelCase property.