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

不使用Linq-to-XML,能否通过System.Xml.Serialization将XML反序列化为字典?

仅用System.Xml.Serialization属性实现XML到字典结构的反序列化

待反序列化的XML

<MessageList category="Alarm" version="1.0.0">
    <Item id="1">
        <Message key="Level" text="Alarm" />
        <Message key="Title" text="ERROR AT PLC UNIT" />
        <Message key="Detail" text="Change PLC unit. &#xD;&#xA;If it is out of order. please contact our service man." />
    </Item>
    <Item id="2">
        <Message key="Level" text="Alarm" />
        <Message key="Title" text="RE-SET PLC UNIT ( PROGRAM FS )" />
        <Message key="Detail" text="Turn off and restart. if the problem persists. check thet the switch on the controller is in RUN mode. &#xD;&#xA;If it is out of order. please contact our service man." />
    </Item>
    <Item id="3">
        <Message key="Level" text="Alarm" />
        <Message key="Title" text="" />
        <Message key="Detail" text="" />
    </Item>
    <Item id="4">
        <Message key="Level" text="Alarm" />
        <Message key="Title" text="" />
        <Message key="Detail" text="" />
    </Item>
    <Item id="5">
        <Message key="Level" text="Alarm" />
        <Message key="Title" text="" />
        <Message key="Detail" text="" />
    </Item>
</MessageList>

期望的类结构

class MessageListClass
{
    public string category { get; set; }
    public string version { get; set; }
    public Dictionary<int, List<Message>> items { get; set; }
}
public class Message
{
    public string key { get; set; }
    public string text { get; set; }
}

当前可运行的非字典版本代码

[XmlRoot("MessageList")]
class MessageList
{
    [XmlAttribute("category")]
    public string category { get; set; }
    [XmlAttribute("version")]
    public string version { get; set; }
    [XmlElement("Item")]
    public List<Item> items { get; set; }
}
public class Item
{
    [XmlAttribute("id")]
    public int alarmId { get; set; }
    [XmlElement("Message")]
    public List<Message> messages { get; set; }
}
public class Message
{
    [XmlAttribute("key")]
    public string key { get; set; }
    [XmlAttribute("text")]
    public string text { get; set; }
}

问题

是否可以不使用Linq-to-XML,仅通过System.Xml.Serialization属性实现上述字典形式的反序列化?


解决方案

可以通过代理属性结合XmlIgnore和XmlElement属性实现,无需Linq-to-XML。核心思路是用可序列化的List<ItemProxy>作为中转,在序列化/反序列化时自动完成与字典结构的转换。

修改后的完整代码

[XmlRoot("MessageList")]
public class MessageListClass
{
    [XmlAttribute("category")]
    public string category { get; set; }

    [XmlAttribute("version")]
    public string version { get; set; }

    // 目标字典,标记为XmlIgnore跳过直接序列化
    [XmlIgnore]
    public Dictionary<int, List<Message>> items { get; set; } = new Dictionary<int, List<Message>>();

    // 代理属性,对应XML中的<Item>节点集合
    [XmlElement("Item")]
    public List<ItemProxy> ItemProxies
    {
        get
        {
            // 字典转代理列表,供序列化输出
            return items.Select(kv => new ItemProxy
            {
                id = kv.Key,
                messages = kv.Value
            }).ToList();
        }
        set
        {
            // 代理列表转字典,完成反序列化赋值
            items = value.ToDictionary(item => item.id, item => item.messages);
        }
    }

    // 内部代理类,完全匹配XML中<Item>的结构
    public class ItemProxy
    {
        [XmlAttribute("id")]
        public int id { get; set; }

        [XmlElement("Message")]
        public List<Message> messages { get; set; } = new List<Message>();
    }
}

public class Message
{
    [XmlAttribute("key")]
    public string key { get; set; }

    [XmlAttribute("text")]
    public string text { get; set; }
}

代码说明

  1. XmlIgnore标记目标字典:让items字典不直接参与XML序列化流程,避免序列化器无法识别字典类型的问题。
  2. 代理属性ItemProxies:用XmlElement("Item")标记,与XML中的<Item>节点一一对应,负责接收和输出XML结构。
  3. 双向转换逻辑:
    • get方法:将字典中的键值对转换为ItemProxy列表,适配XML序列化的格式要求。
    • set方法:将反序列化得到的ItemProxy列表转换为字典结构,赋值给目标items属性。
  4. ItemProxy类:完全映射XML中<Item>节点的结构,包含id属性和Message列表,保证序列化/反序列化的正确性。

反序列化测试示例

using System.Xml.Serialization;
using System.IO;

// 读取XML文件内容
string xmlContent = File.ReadAllText("alarm-messages.xml");

// 创建序列化器
XmlSerializer serializer = new XmlSerializer(typeof(MessageListClass));

// 执行反序列化
using (StringReader reader = new StringReader(xmlContent))
{
    MessageListClass result = (MessageListClass)serializer.Deserialize(reader);
    // result.items即为目标字典结构,可直接按id索引访问对应Message列表
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 05:43:23