添加额外属性的自定义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();
}

添加额外属性的自定义XML序列化

如果你想输出一个属性,你需要一个被序列化为属性的属性。试试以下命令:

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&quot;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>
我希望这对有类似问题的人来说是一个解决方案。