You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

反序列化时如何将多个XML属性映射到单个C#属性?

问题描述

我需要用XmlSerializer反序列化XML时,让单个C#属性BloodKind能映射到XML元素的多个属性名(比如blooded或bloodtype)。但[XmlAttribute]不允许多个特性叠加,[XmlChoiceIdentifier]也不支持属性场景;如果为每个属性名单独创建C#属性,会导致类臃肿且需要大量空值检查,而且我无法修改源XML结构。

示例XML:

<Animal blooded="warm"> <!-- 属性可能是"blooded"、"bloodtype"等 -->
    <Horse>Jack</Horse>
    <Chicken>Charlie</Chicken>
</Animal>

期望的C#类写法(但无法直接实现):

[Serializable]
public partial class Animal
{
    public string Horse { get; set; }
    public string Chicken { get; set; }

    [XmlAttribute("blooded")]
    [XmlAttribute("bloodtype")] // 希望支持多个属性名映射到同一个属性
    public string BloodKind { get; set; }
}

方案一:使用XmlAttributeOverrides动态构建序列化器

通过XmlAttributeOverrides可以为同一个C#属性动态注册多个XML属性名称,无需在类中定义冗余属性,序列化器会自动处理多属性映射。

代码示例:

[Serializable]
public partial class Animal
{
    public string Horse { get; set; }
    public string Chicken { get; set; }
    public string BloodKind { get; set; }
}

public class Program
{
    public static void Main(string[] args)
    {
        // 创建属性覆盖配置
        var overrides = new XmlAttributeOverrides();
        var attrs = new XmlAttributes();
        // 为BloodKind添加多个XML属性映射
        attrs.XmlAttributes.Add(new XmlAttributeAttribute("blooded"));
        attrs.XmlAttributes.Add(new XmlAttributeAttribute("bloodtype"));
        overrides.Add(typeof(Animal), nameof(Animal.BloodKind), attrs);

        // 使用覆盖配置创建序列化器
        XmlSerializer serializer = new XmlSerializer(typeof(Animal), overrides);
        using Stream reader = new FileStream("data.xml", FileMode.Open);
        Animal animal = (Animal)serializer.Deserialize(reader);

        Console.WriteLine(animal.BloodKind); // 输出"warm"
    }
}

注意:若多次创建相同配置的XmlSerializer,建议缓存实例,避免因重复生成动态程序集导致内存泄漏。


方案二:实现IXmlSerializable接口手动处理属性

如果需要更灵活的控制(比如属性名数量较多或需自定义逻辑),可以实现IXmlSerializable接口,手动读取XML属性值。

代码示例:

public class Animal : IXmlSerializable
{
    public string Horse { get; set; }
    public string Chicken { get; set; }
    public string BloodKind { get; set; }

    public System.Xml.Schema.XmlSchema GetSchema() => null;

    public void ReadXml(System.Xml.XmlReader reader)
    {
        // 遍历所有属性,匹配目标名称
        while (reader.MoveToNextAttribute())
        {
            if (reader.Name is "blooded" or "bloodtype")
            {
                BloodKind = reader.Value;
            }
        }

        // 回到元素节点,读取子元素
        reader.MoveToElement();
        reader.ReadStartElement();

        while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
        {
            switch (reader.Name)
            {
                case "Horse":
                    Horse = reader.ReadElementContentAsString();
                    break;
                case "Chicken":
                    Chicken = reader.ReadElementContentAsString();
                    break;
                default:
                    reader.Skip(); // 跳过未知元素
                    break;
            }
        }
        reader.ReadEndElement();
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        // 序列化时选择输出其中一个属性名(比如"blooded")
        if (!string.IsNullOrEmpty(BloodKind))
        {
            writer.WriteAttributeString("blooded", BloodKind);
        }
        if (!string.IsNullOrEmpty(Horse))
        {
            writer.WriteElementString("Horse", Horse);
        }
        if (!string.IsNullOrEmpty(Chicken))
        {
            writer.WriteElementString("Chicken", Chicken);
        }
    }
}

public class Program
{
    public static void Main(string[] args)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(Animal));
        using Stream reader = new FileStream("data.xml", FileMode.Open);
        Animal animal = (Animal)serializer.Deserialize(reader);

        Console.WriteLine(animal.BloodKind); // 输出"warm"
    }
}

该方案完全自定义XML读写逻辑,不受默认XmlSerializer特性限制,适合复杂映射场景。


内容的提问来源于stack exchange,提问作者Hysperr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 00:20:56