将XML属性反序列化为Dictionary

本文关键字:string object Dictionary XML 属性 反序列化 | 更新日期: 2023-09-27 18:01:32

假设我正在尝试反序列化以下XML(在c#程序中):

<Data>
    <DataItem Id="1" Attrib1="Val1_1" Attrib2="Val2_1" Attrib3="Val3_1" />
    <DataItem Id="2" Attrib1="Val1_2" Attrib4="Val4_2" />
    <DataItem Id="3" Attrib3="Val3_1" Attrib5="Val5_3" />
</Data>

因此,每个DataItem元素将有一个Id字段和我想捕获/存储的一组随机属性。

我想象的最终包含类可能如下所示:

[XmlRootAttribute("Data")]
public class Data
{
    [XmlElement("DataItem")]
    public DataItem[] Items { get; set; }
}
public class DataItem
{
    public Dictionary<string, object> Vals { get; set; }
    [XmlIgnore]
    public string Id { get { return (string)Vals[Id]; } }
}

(如果我在这个结构上错了,请让我知道-这对我来说仍然是非常新的!!)

但我不确定如何将属性反序列化为我的字典的[Key][Value]对。我发现这个问题,也是这个其他的答案,似乎是指向我在正确的(虽然不同)方向,但我迷失在如何正确地实现这一点,知道这应该是相当容易的。

任何关于如何做到这一点的帮助/链接/样本将非常感激!!

谢谢! !

将XML属性反序列化为Dictionary<string, object>

更通用的解决方案是:

public class DynamicAttributes : IXmlSerializable, IDictionary<string, object>
{
    private readonly Dictionary<string, object> _attributes;
    public DynamicAttributes()
    {
        _attributes = new Dictionary<string, object>();
    }
    public XmlSchema GetSchema()
    {
        return null;
    }
    public void ReadXml(XmlReader reader)
    {
        if (reader.HasAttributes)
        {
            while (reader.MoveToNextAttribute())
            {
                var key = reader.LocalName;
                var value = reader.Value;
                _attributes.Add(key, value);
            }
            // back to the owner of attributes
            reader.MoveToElement();
        }
        reader.ReadStartElement();
    }
    public void WriteXml(XmlWriter writer)
    {
        foreach (var attribute in _attributes)
        {
            writer.WriteStartAttribute(attribute.Key);
            writer.WriteValue(attribute.Value);
            writer.WriteEndAttribute();
        }
    }
    // implementation of IDictionary<string, object> comes here
}

那么你的类应该是:

[XmlRoot("Data")]
public class Data
{
    [XmlElement("DataItem")]
    public DataItem[] Items { get; set; }
}
public class DataItem : DynamicAttributes
{
    [XmlIgnore]
    public string Id
    { 
        get
        {                
            return this.TryGetValue("Id", out var value) ? value.ToString() : null;
        } 
    }
}

好,所以正如我所怀疑的(并且在评论中建议的),我把直接XML序列化放在一边,编写了我自己的解析方法来完成它。

对于其他人这可能会有所帮助,这是我最后写的-希望它也能帮助你(如果有人有更好的答案,尽管,请发帖!-我很想看看还有什么办法可以做到/做得更好):

public class Data
{
    public List<DataItem> Items { get; set; }
    private Data(XElement root)
    {
        Items = new List<DataItem>();
        foreach (XElement el in root.Elements())
        {
            Items.Add(new DataItem(el));
        }
    }
    public static Data Load(Stream stream)
    {
        return new Data(XDocument.Load(stream).Root);
    }
}
public class DataItem
{
    public Dictionary<string, string> Vals;
    public string Id { get { return (string)Vals["Id"]; } }
    public DataItem(XElement el)
        {
            Vals = new Dictionary<string, string>();
            // Load all the element attributes into the Attributes Dictionary
            foreach (XAttribute att in el.Attributes())
            {
                string name = att.Name.ToString();
                string val = att.Value;
                Vals.Add(name, val);
            }
        }
}

那么它将在代码中相当简单地使用:

Data MyData = Data.Load(MyXMLStream);

希望这也能帮助到其他人!!

Use This

<Data>
    <DataItem Id="1" Val="Val1_1" />
    <DataItem Id="1" Val="Val2_1" />
    <DataItem Id="1" Val="Val3_1" />
    <DataItem Id="2" Val="Val1_2" />
    <DataItem Id="2" Val="Val4_2" />
    <DataItem Id="3" Val="Val3_1" />
    <DataItem Id="3" Val="Val5_3" />
</Data>