[英]XML Deserialization with dynamic fields
Say I have the following xml: 说我有以下xml:
<rootelement>
<childone>val1</childone>
<childtwo>val2</childtwo>
<childthree>val3</childthree>
</rootelement>
To deserialize it into an object I'd normally have something like this: 要将其反序列化为对象,通常需要这样的东西:
public class rootelement{
public string childone,childtwo,childthree;
}
That all works, but now I want to find out if I can have the child node names stored in an array or something so I can manage my fields more easily, and use this array to populate the keys in a List
of KeyValuePair
eg: 一切正常,但是现在我想知道是否可以将子节点名称存储在数组中或其他内容中,以便可以更轻松地管理字段,并使用此数组填充
KeyValuePair
List
中的键,例如:
string[] fieldnames={"childone","childtwo","childthree"};
List<KeyValuePair<string, string>> fields=new List<KeyValuePair<string, string>>();
for(int i=0;i<fieldnames.Length;i++){
fields.Add(new KeyValuePair<string,string>(fieldnames[i],""));
}
And the last step would be for deserialization to populate the values. 最后一步是反序列化以填充值。 It doesn't have to be a
List
of KeyValuePair
specifically, anything that I could apply the same concept to would work. 它不必一定是
KeyValuePair
的List
,任何我可以应用相同概念的方法都可以使用。
Is something like this possible? 这样的事情可能吗? If so, please assist me with an example.
如果是这样,请举例帮助我。
What I ended up doing was the following: 我最终要做的是以下几点:
public class MyXmlRoot{
private string[] allowedTags={"tagA","tagB","tagC"};
[XmlAnyElement]
public List<XmlElement> children = new List<XmlElement>(); //populated after serialization
public string GetValueByKey(string key){
return children.Find(k => k.Name == key).InnerText;
}
public void UseTags(){
for(int i=0;i<allowedTags.Length;i++){
Console.WriteLine(allowedTags[i]+" = "+GetValueByKey(allowedTags[i]));
}
}
}
If my understanding is correct, you need to deserialize manually. 如果我的理解是正确的,则需要手动反序列化。 One of the optoins to do that is using XDocument:
使用XDocument的操作之一是:
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Xml.Linq;
using System.Xml.XPath;
class Program
{
class Children
{
public string one { get; set; }
public string two { get; set; }
}
static void Main(string[] args)
{
string xmlstr = @"<?xml version=""1.0"" encoding=""utf-8""?>
<rootelement>
<childone>val1</childone>
<childtwo>val2</childtwo>
<childthree>val3</childthree>
<children1>
<children2>
<one>val1-1</one>
<two>val1-2</two>
<three>val1-3</three>
</children2>
</children1>
</rootelement>";
XDocument xml = XDocument.Parse(xmlstr);
string[] fieldnames = { "childone", "childtwo", "childthree" };
List<KeyValuePair<string, string>> fields = new List<KeyValuePair<string, string>>();
foreach (string i in fieldnames)
{
XElement elem = xml.Root.XPathSelectElement(i);
if (elem != null)
{
fields.Add(new KeyValuePair<string, string>(i, elem.Value));
}
}
// Debug
foreach (KeyValuePair<string, string> f in fields)
{
Console.WriteLine(f);
}
// Try to fill specific object's properties with using reflection
string parentPath = "children1/children2";
string[] names = { "one", "two", "three" };
Children childrenFields = new Children();
foreach (var name in names)
{
PropertyInfo prop = typeof(Children).GetProperty(name);
if (prop != null)
{
XElement elem = xml.Root.XPathSelectElement(parentPath + "/" + name);
if (elem != null)
{
prop.SetValue(childrenFields, elem.Value, null);
}
}
}
// Debug
Console.WriteLine("Children one: {0}, two: {1}",
childrenFields.one, childrenFields.two);
}
}
This code uses System.Xml.XPath.Extensions.XPathSelectElement
extension method to find the target XML element by using XPath to support more complex XML document, such as children1
element in my example. 此代码使用
System.Xml.XPath.Extensions.XPathSelectElement
扩展方法通过使用XPath支持更复杂的XML文档(例如本例中的children1
元素)来查找目标XML元素。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.