将 XML 属性反序列化到字典 <string, object>
Deserialize XML Attributes to Dictionary<string, object>
假设我正在尝试反序列化以下 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 question and also this other answer 似乎为我指明了正确(尽管不同)的方向,但我不知道如何正确实施它并且知道这应该相当容易。
任何有关如何完成此操作的帮助/链接/示例将不胜感激!
谢谢!!!
使用这个
<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>
好吧,正如我所怀疑的(并且在评论中被建议),我放弃了直接 XML 序列化并编写了我自己的解析方法来完成这个。
对于其他人这可能有帮助,这就是我最后写的 - 希望它也能帮助你(不过,如果有人有更好的答案,请 post 它! - 我很想看看这还能如何完成/做得更好):
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);
希望这对其他人也有帮助!!
更通用的解决方案是:
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(在 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 question and also this other answer 似乎为我指明了正确(尽管不同)的方向,但我不知道如何正确实施它并且知道这应该相当容易。
任何有关如何完成此操作的帮助/链接/示例将不胜感激!
谢谢!!!
使用这个
<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>
好吧,正如我所怀疑的(并且在评论中被建议),我放弃了直接 XML 序列化并编写了我自己的解析方法来完成这个。
对于其他人这可能有帮助,这就是我最后写的 - 希望它也能帮助你(不过,如果有人有更好的答案,请 post 它! - 我很想看看这还能如何完成/做得更好):
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);
希望这对其他人也有帮助!!
更通用的解决方案是:
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;
}
}
}