Reputation: 6717
I have a serialier that is not totally unlike the following:
[Serializable]
public class MSG
{
[XmlAttribute]
public string Name { get; set; } = string.Empty;
[XmlText]
public string Content { get; set; } = string.Empty;
}
public MSG DeserializeMyMsg(string xmlstr)
{
TextReader reader = new StringReader(xmlstr);
var serializer = new XmlSerializer(typeof(MSG));
MSG ret = serializer.Deserialize(reader) as MSG;
return ret;
}
This would successfully deserialize the following:
<MSG Name="woho">any content</MSG>
Occasionally data can arrive as:
<Mg Name="woho">any content</Mg>
How can I mark Mg
as an alternative name for MSG
?
MSG is the root. Fixing Mg would be the long term goal but is not an option either. The messages could be retrofitted with an outer root.
Upvotes: 1
Views: 752
Reputation: 4994
AFAIK, it is not directly possible with only modifying the serialization attributes. But what you could do, is introduce another type with different attributes and then adjust your deserialization logic to choose a proper serializer.
Model for legacy:
[XmlRoot("Mg")]
public class MSGLegacyWrapper : MSG { }
Deserialization logic:
public static MSG DeserializeMyMsg(string xmlstr)
{
using (var reader = new StringReader(xmlstr))
using (var xmlreader = XmlReader.Create(reader))
using (var serializationReader = new StringReader(xmlstr))
{
var serializer = new XmlSerializer(typeof(MSG));
var chosenSerializer = serializer.CanDeserialize(xmlreader)
? serializer
: new XmlSerializer(typeof(MSGLegacyWrapper));
return chosenSerializer.Deserialize(serializationReader) as MSG;
}
}
Ofc this could be pimped further to optimize the decision process.
Alternative 1
If you are already preprocessing the input then you could as well normalize the root tag name with string operations (ex regex) before deserializing to strongly typed model.
Alternative 2
If your schema is simple/stable enough, you could drop attribute-based deserialization and implement your own custom XmlReader
which CAN handle alternative root elements. See documentation and examples from MSDN.
I believe if performance matters then this is the fastest option.
Upvotes: 1
Reputation: 4679
You mentioned in a comment you could wrap your xml. This feels an awful lot like a hack but this works. Generally my advice would be don't do this!
So your xml would be:
<NewRoot><MSG Name="woho">any content</MSG></NewRoot>
Or
<NewRoot><Mg Name="woho">any content</Mg></NewRoot>
Then define these classes and deserialize the above xml:
public class NewRoot
{
[XmlElement("MSG", typeof(MSG))]
[XmlElement("Mg", typeof(Mg))]
public MSG Msg {get;set;}
}
public class Mg : MSG {}
Upvotes: 1