【问题标题】:Deserialize XML Attributes to Dictionary<string, object>将 XML 属性反序列化为 Dictionary<string, object>
【发布时间】:2015-07-08 14:40:48
【问题描述】:

假设我正在尝试反序列化以下 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] 对。 我发现this questionthis other answer 似乎指向了我正确的方向(尽管不同),但我不知道如何正确实现它,并且知道这应该相当容易。

非常感谢任何有关如何完成此操作的帮助/链接/示例!

谢谢!!!

【问题讨论】:

  • 你不可能用属性来做这件事。您需要实现IXmlSerializable 并手动编写DataItem 的序列化代码。

标签: c# xml dictionary serialization deserialization


【解决方案1】:

更通用的解决方案是:

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;
        } 
    }
}

【讨论】:

  • 真是太好了!!
【解决方案2】:

好吧,正如我所怀疑的(并且在 cmets 中被建议),我将直接 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);

希望这对其他人也有帮助!

【讨论】:

    【解决方案3】:

    使用这个

    <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>
    

    【讨论】:

    • 对不起,@jdweng,这对我来说甚至没有意义....给出了 XML,我在问如何将其反序列化为字典....跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-10
    • 1970-01-01
    • 1970-01-01
    • 2011-01-04
    • 1970-01-01
    • 2021-08-10
    相关资源
    最近更新 更多