Reputation: 73
I have the following class.
public class ConfigurationItem
{
public String Type { get; set; }
public String Value { get; set; }
}
This code performs the serialization.
static void Main(string[] args)
{
List<ConfigurationItem> cis = new List<ConfigurationItem>();
cis.Add(new ConfigurationItem() { Type = "Car", Value = "Car Value" });
cis.Add(new ConfigurationItem() { Type = "Bike", Value = "Bike Value" });
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(cis.GetType());
x.Serialize(Console.Out, cis);
}
The actual output is below.
<?xml version="1.0" encoding="IBM437"?>
<ArrayOfConfigurationItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ConfigurationItem>
<Type>Car</Type>
<Value>Car Value</Value>
</ConfigurationItem>
<ConfigurationItem>
<Type>Bike</Type>
<Value>Bike Value</Value>
</ConfigurationItem>
</ArrayOfConfigurationItem>
I would like to produce the following XML.
<?xml version="1.0" encoding="IBM437"?>
<ArrayOfConfigurationItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ConfigurationItem>
<Type>Car</Type>
<Value Label="Car Label">Car Value</Value>
</ConfigurationItem>
<ConfigurationItem>
<Type>Bike</Type>
<Value Label="Bike Label">Bike Value</Value>
</ConfigurationItem>
</ArrayOfConfigurationItem>
I have following type to Label mapping table available
Dictionary<String, String> ValueLabels = new Dictionary<string, string>()
{
{"Car","Car Label"},
{"Bike","Bike Label"}
};
I can't touch the ConfigurationItem class. Is it possible to use System.Xml.Serialization.XmlAttributeOverrides or something similar?
Edit 1 I have an ugly solution that I'm using now. I'm using normal serialization and adding data to the XmlDocument manually.
static void Main(string[] args)
{
List<ConfigurationItem> cis = new List<ConfigurationItem>();
cis.Add(new ConfigurationItem(){Type = "Car", Value = "Car Value"});
cis.Add(new ConfigurationItem(){Type = "Bike", Value = "Bike Value"});
Dictionary<String, String> valueLabels = new Dictionary<string, string>()
{
{"Car","Car Label"},
{"Bike","Bike Label"}
};
var detailDocument = new System.Xml.XmlDocument();
var nav = detailDocument.CreateNavigator();
if (nav != null)
{
using (System.Xml.XmlWriter w = nav.AppendChild())
{
var ser = new System.Xml.Serialization.XmlSerializer(cis.GetType());
ser.Serialize(w, cis);
}
}
var nodeList = detailDocument.DocumentElement.SelectNodes("//ConfigurationItem");
foreach (System.Xml.XmlNode node in nodeList)
{
String type = ((System.Xml.XmlElement)node.SelectNodes("Type")[0]).InnerText;
((System.Xml.XmlElement)node.SelectNodes("Value")[0]).SetAttribute("Label", valueLabels[type]);
}
System.Xml.XmlTextWriter writer = new System.Xml.XmlTextWriter(Console.Out);
writer.Formatting = System.Xml.Formatting.Indented;
detailDocument.WriteTo(writer);
Console.ReadLine();
}
Still looking for better solution...
Upvotes: 4
Views: 4372
Reputation: 44
It's been a long time since the issue. But I hope it will be a solution for those who have similar problem.
For the "Value" xml node;
[XmlRoot("Value")]
public class ValueNode
{
public ValueNode()
{
}
public ValueNode(string label, string value)
{
Label = label;
Value = value;
}
[XmlAttribute]
public string Label { get; set; }
[XmlText]
public string Value { get; set; }
}
For the "ConfigurationItem" xml node;
[XmlRoot("ConfigurationItem")]
public class ConfigurationItemWrapper
{
private static readonly Dictionary<string, string> ValueLabels = new Dictionary<string, string>()
{
{"Car","Car Label"},
{"Bike","Bike Label"}
};
public ConfigurationItemWrapper()
{
}
public ConfigurationItemWrapper(ConfigurationItem item)
{
if (item is null)
{
throw new ArgumentNullException(nameof(item));
}
Type = item.Type;
Value = new ValueNode(
ValueLabels.ContainsKey(item.Type)
? ValueLabels[item.Type]
: null,
item.Value);
}
public string Type { get; set; }
public ValueNode Value { get; set; }
public static explicit operator ConfigurationItem(ConfigurationItemWrapper item)
{
return (item is null)
? null
: new ConfigurationItem() { Type = item.Type, Value = item.Value?.Value };
}
public static explicit operator ConfigurationItemWrapper(ConfigurationItem item)
{
return (item is null)
? null
: new ConfigurationItemWrapper(item);
}
}
To serialize the "List<ConfigurationItem>" list in the expected format;
[XmlRoot("ArrayOfConfigurationItem")]
public class ConfigurationItemListWrapper
{
public ConfigurationItemListWrapper()
{
Items = new List<ConfigurationItemWrapper>();
}
public ConfigurationItemListWrapper(IEnumerable<ConfigurationItem> items)
{
Items = new List<ConfigurationItemWrapper>(items.Select(x => (ConfigurationItemWrapper)x));
}
[XmlElement("ConfigurationItem")]
public List<ConfigurationItemWrapper> Items { get; set; }
}
Use of;
static void Main(string[] args)
{
List<ConfigurationItem> cis = new List<ConfigurationItem>();
cis.Add(new ConfigurationItem() { Type = "Car", Value = "Car Value" });
cis.Add(new ConfigurationItem() { Type = "Bike", Value = "Bike Value" });
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(ConfigurationItemListWrapper));
x.Serialize(Console.Out, new ConfigurationItemListWrapper(cis));
Console.ReadLine();
}
The expected console output will be as follows.
<?xml version="1.0" encoding="IBM437"?>
<ArrayOfConfigurationItem xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ConfigurationItem>
<Type>Car</Type>
<Value Label="Car Label">Car Value</Value>
</ConfigurationItem>
<ConfigurationItem>
<Type>Bike</Type>
<Value Label="Bike Label">Bike Value</Value>
</ConfigurationItem>
</ArrayOfConfigurationItem>
I hope it will be a solution for those who have similar problem.
Upvotes: 0
Reputation: 161773
If you want to output an attribute, you'll need a property which will be serialized as the attribute. Try the following:
public class ConfigurationItem
{
public String Type { get; set; }
public String Value { get; set; }
[XmlAttribute("Label")]
public string Label
{
get {return Value;}
set {Value = value;}
}
}
Upvotes: 3