I have class with XMLRoot and one XMLElement on array. Based on client, when i serialize my class i have to change XMLRoot and XMLElement. Is there a way to change it dynamically
[XmlRoot("sample")]
public class MyData
{
private ArrayList map;
public MyData()
{
map = new ArrayList();
}
[XmlElement("url")]
public Location[] Locations
{
get
{
Location[] items = new Location[map.Count];
map.CopyTo(items);
return items;
}
set
{
if (value == null)
return;
Location[] items = (Location[])value;
map.Clear();
foreach (Location item in items)
map.Add(item);
}
}
public int Add(Location item)
{
return map.Add(item);
}
}
As you can see, my root is "sample", based on client it can be "sample" or "reserved". XMLElement is "url" and based on client it can be "url" or "dataitem"
I'm serializing using XMLSerializer
// My condition needs to be here to determine which
// root and xmlelement should use
var xs = new XmlSerializer(typeof(MyData));
var oString = new StringWriterWithEncoding(Encoding.UTF8);
Thanks in advance
See MSDN-Overrides on XmlSerializer
You can supply Overrides via the constructor - best read the doku.
Example:
using System.Collections;
using System.Linq;
using System.Xml;
using System.Xml.Serialization;
public class Location
{
public string L;
}
[XmlRoot("sample")]
public class MyData
{
public MyData()
{
map = new ArrayList();
}
[XmlElement("url")]
public Location[] Locations
{
get
{
Location[] items = new Location[map.Count];
map.CopyTo(items);
return items;
}
set
{
if (value == null)
return;
Location[] items = (Location[])value;
map.Clear();
foreach (Location item in items)
map.Add(item);
}
}
public int Add(Location item)
{
return map.Add(item);
}
private ArrayList map;
}
internal class Program
{
Xml Print To Screen:
private static void DoSerialize(MyData m, XmlSerializer xs)
{
var settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
settings.Indent = true;
settings.NewLineOnAttributes = true;
var sww = new System.IO.StringWriter();
XmlWriter writer = XmlWriter.Create(sww, settings);
xs.Serialize(writer, m);
Console.WriteLine(sww.ToString().Replace("><", ">\r\n<"));
}
Usage of overloaded Constructor:
static void Main()
{
// testdata
MyData m = new MyData
{
Locations = new Location[2]
{
new Location { L = "L1" },
new Location { L = "L2" }
}
};
// simple Serializer
var xs = new XmlSerializer(typeof(MyData));
DoSerialize(m, xs);
Console.WriteLine();
var xs2 = new XmlSerializer(typeof(MyData), XmlAttributeOverride(),
new Type[] { typeof(Location[]) }, RootOverride(), "");
DoSerialize(m, xs2);
Console.ReadLine();
}
// override the root node
private static XmlRootAttribute RootOverride() => new XmlRootAttribute("OtherName");
// override your Languages property
private static XmlAttributeOverrides XmlAttributeOverride()
{
var attrs = new XmlAttributes();
attrs.XmlElements.Add(new XmlElementAttribute("Location"));
var o = new XmlAttributeOverrides();
o.Add(typeof(MyData), "Locations", attrs);
return o;
}
}
Output:
<sample xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://
www.w3.org/2001/XMLSchema">
<url>
<L>L1</L>
</url>
<url>
<L>L2</L>
</url>
</sample>
<OtherName xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http
://www.w3.org/2001/XMLSchema">
<Location>
<L>L1</L>
</Location>
<Location>
<L>L2</L>
</Location>
</OtherName>