使用动态字段进行XML反序列化

时间:2014-09-05 04:42:33

标签: c# .net xml serialization

说我有以下xml:

<rootelement>
    <childone>val1</childone>
    <childtwo>val2</childtwo>
    <childthree>val3</childthree>
</rootelement>

要将其反序列化为对象,我通常会遇到这样的事情:

public class rootelement{
    public string childone,childtwo,childthree;
}

这一切都有效,但现在我想知道我是否可以将子节点名称存储在数组中,以便更容易管理我的字段,并使用此数组填充{{1}中的键} List例如:

KeyValuePair

最后一步是反序列化来填充值。 它不一定是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],"")); } List具体,我可以应用相同的概念来工作。

这样的事情可能吗?如果是这样,请帮我举个例子。

2 个答案:

答案 0 :(得分:1)

我最终做的是以下内容:

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

}

答案 1 :(得分:0)

如果我的理解是正确的,您需要手动反序列化。 其中一个选择是使用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);
    }
}

此代码使用System.Xml.XPath.Extensions.XPathSelectElement扩展方法通过使用XPath来查找目标XML元素,以支持更复杂的XML文档,例如我的示例中的children1元素。