添加额外属性的自定义XML序列化
本文关键字:自定义 XML 序列化 属性 添加 | 更新日期: 2023-09-27 18:10:51
我有以下类:
public class ConfigurationItem
{
public String Type { get; set; }
public String Value { get; set; }
}
这段代码执行序列化。
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);
}
实际输出如下:
<?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>
我想生成以下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>
我有以下类型到标签映射表可用
Dictionary<String, String> ValueLabels = new Dictionary<string, string>()
{
{"Car","Car Label"},
{"Bike","Bike Label"}
};
我不能触摸ConfigurationItem类。是否可以使用System.Xml.Serialization.XmlAttributeOverrides或类似的方法?
编辑1 我现在正在使用一个丑陋的解决方案。我使用普通的序列化并手动向XmlDocument添加数据。
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();
}
如果你想输出一个属性,你需要一个被序列化为属性的属性。试试以下命令:
public class ConfigurationItem
{
public String Type { get; set; }
public String Value { get; set; }
[XmlAttribute("Label")]
public string Label
{
get {return Value;}
set {Value = value;}
}
}
这个问题已经过去很长时间了。但我希望这对那些有类似问题的人来说是一个解决方案。
For"Value"xml节点;
[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; }
}
<ConfigurationItem"xml节点;>
[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);
}
}
序列化列表
[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; }
}
使用;
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();
}
预期的控制台输出将如下所示:
<?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>