C# 将键值对XML反序列化到类对象

C# 将键值对XML反序列化到类对象,c#,asp.net,xml,deserialization,xml-deserialization,C#,Asp.net,Xml,Deserialization,Xml Deserialization,我有一个包含键值对的XML,如下所述: <Employee> <item> <key>Name</key> <value>XYZ</value> </item> <item> <key>Phone</key> <value>1234567890</value>

我有一个包含键值对的XML,如下所述:

<Employee>
    <item>
        <key>Name</key>
        <value>XYZ</value>
    </item>
    <item>
        <key>Phone</key>
        <value>1234567890</value>
    </item>
    <item>
        <key>Date of Birth</key>
        <value>19-06-1984</value>
    </item>
    <item>
        <key>Employee ID</key>
        <value>1</value>
    </item>
</Employee>
public class Employee
{
    public string Name { get; set; }

    public string Phone { get; set; }

    public DateTime? DOB { get; set; }

    public int? Id { get; set; }
}
我需要将这个XML反序列化为属性类,但我不知道实现这个目的的正确方法

我可以使用
反射
来实现它,但我听说
反射
会降低性能,所以想知道有没有更好的方法来实现这一点

这应该可以

List<Employee> employees = new List<Employee>();
XElement xElement = XElement.Load("Employees.xml");
IEnumerable<XElement> xmlEmployees = xElement.Elements("Employee");
foreach (var xmlEmployee in xmlEmployees)
{
    Employee employee = new Employee();
    foreach (var item in xmlEmployee.Elements("item"))
    {
        string key = item.Element("key").Value;
        string value = item.Element("value").Value;
        switch (key)
        {
            case "Name":
                employee.Name = value;
                break;
            ...
        }
    }
    employees.Add(employee);
}
List employees=newlist();
XElement=XElement.Load(“Employees.xml”);
IEnumerable xmlEmployees=xElement.Elements(“雇员”);
foreach(xmlEmployees中的XmlEmployeer变量)
{
员工=新员工();
foreach(xmlEmployee.Elements(“项”)中的var项)
{
字符串键=item.Element(“键”).Value;
字符串值=item.Element(“value”).value;
开关(钥匙)
{
案例“名称”:
employee.Name=value;
打破
...
}
}
employees.Add(employees);
}

实现
IXmlSerializable
如下:

public class Employee : IXmlSerializable
{
    public string Name { get; set; }

    public string Phone { get; set; }

    public DateTime? DOB { get; set; }

    public int? Id { get; set; }

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        while (reader.Read())
        {
            switch (reader.NodeType)
            {
                case XmlNodeType.Element:
                    if (string.Equals(reader.Name, "item", StringComparison.InvariantCultureIgnoreCase))
                    {
                        // move to 'key'
                        reader.Read();
                        if (reader.Name != "key") throw new SerializationException();
                        string key = reader.ReadElementContentAsString();
                        if (reader.Name != "value") throw new SerializationException();
                        switch (key)
                        {
                            case "Name":
                                this.Name = reader.ReadElementContentAsString();
                                break;
                            case "Phone":
                                this.Phone = reader.ReadElementContentAsString();
                                break;
                            case "Date of Birth":
                                this.DOB = DateTime.Parse(reader.ReadElementContentAsString());
                                break;
                            case "Employee ID":
                                this.Id = reader.ReadElementContentAsInt();
                                break;
                        }
                    }
                    else
                    {
                        // something was wrong
                        throw new SerializationException();
                    }
                    break;
                case XmlNodeType.EndElement:
                    reader.Read();
                    return;
            }
        }
    }

    public void WriteXml(XmlWriter writer)
    {
        throw new NotImplementedException();
    }
}
并与标准的XmlSerializer一起使用:

XmlSerializer ser = new XmlSerializer(typeof(Employee));
using (var stream = File.OpenRead(@"D:\Temp\employee.xml"))
{
    var item = ser.Deserialize(stream);
}
渴望类

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class Employee
{

    private EmployeeItem[] itemsField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("item", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public EmployeeItem[] Items
    {
        get
        {
            return this.itemsField;
        }
        set
        {
            this.itemsField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class EmployeeItem
{

    private string keyField;

    private string valueField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string key
    {
        get
        {
            return this.keyField;
        }
        set
        {
            this.keyField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string value
    {
        get
        {
            return this.valueField;
        }
        set
        {
            this.valueField = value;
        }
    }
}
[System.CodeDom.Compiler.GeneratedCodeAttribute(“xsd”、“4.0.30319.1”)]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute(“代码”)]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace=”“,IsNullable=false)]
公共部分类雇员
{
私人雇员项目[]项目字段;
/// 
[System.Xml.Serialization.xmlementAttribute(“item”,Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
公共雇员项目[]项目
{
得到
{
返回此.itemsField;
}
设置
{
this.itemsField=值;
}
}
}
/// 
[System.CodeDom.Compiler.GeneratedCodeAttribute(“xsd”,“4.0.30319.1”)]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute(“代码”)]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
公共部分类EmployeeItem
{
私有字符串键域;
私有字符串值字段;
/// 
[System.Xml.Serialization.xmlementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
公共字符串密钥
{
得到
{
返回这个.keyField;
}
设置
{
this.keyField=值;
}
}
/// 
[System.Xml.Serialization.xmlementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
公共字符串值
{
得到
{
返回此.valueField;
}
设置
{
this.valueField=值;
}
}
}
我不喜欢这个解决方案,因为它的复杂性超过了它应有的程度。
如果我面对这个任务,我会使用automapper。但是我不记得它的正确语法。

尝试使用LINQ to XML实现这一点,如果运气不好,请先自己尝试一些东西-将代码发布到此处反射可能会降低性能,但在大多数应用程序中,您可能不会注意到它。@Moo Juice:您是对的。但是我有非常大的xml。这只是我提供的一个示例。@YuvalItzchakov:我听说了
XmlSerializer
,但您认为有问题的XML可以反序列化到此对象吗?@user2988458我没有注意到您以键值的方式存储它。
You can give this a try. This is simple and subtle.

   using System;
   using System.IO;
   using System.Xml.Serialization;
   using System.Xml;
   using System.Text;

   namespace ConsoleApplication1
   {
       class Program
       {
            static void Main(string[] args)
            {
                 Employee emp = new Employee
                 {
                     Name = new Item { Key = "Name", Value = "XYZ" },
                     Phone = new Item { Key = "Phone", Value = "007987" },
                     DOB = new Item { Key = "Date of Birth", Value = "Some Date"},
                     Id = new Item { Key = "Employee ID", Value = "A ID" },
                 };

            var ser = new XmlSerializer(typeof(Employee));

            using (var fs = new StreamWriter("your path", false))
            {
                ser.Serialize(fs, emp);
            }

            var emp2 = ser.Deserialize(new StreamReader("your path"));
        }
    }

    public class Employee
    {
        [XmlElement(ElementName = "item1")]
        public Item Name { get; set; }`enter code here`

        [XmlElement(ElementName = "item2")]
        public Item Phone { get; set; }

        [XmlElement(ElementName = "item3")]
        public Item DOB { get; set; }

        [XmlElement(ElementName = "item4")]
        public Item Id { get; set; }
    }

    public class Item
    {
        public string Key { get; set; }
        public string Value { get; set; }
    }
}
You can give this a try. This is simple and subtle.

   using System;
   using System.IO;
   using System.Xml.Serialization;
   using System.Xml;
   using System.Text;

   namespace ConsoleApplication1
   {
       class Program
       {
            static void Main(string[] args)
            {
                 Employee emp = new Employee
                 {
                     Name = new Item { Key = "Name", Value = "XYZ" },
                     Phone = new Item { Key = "Phone", Value = "007987" },
                     DOB = new Item { Key = "Date of Birth", Value = "Some Date"},
                     Id = new Item { Key = "Employee ID", Value = "A ID" },
                 };

            var ser = new XmlSerializer(typeof(Employee));

            using (var fs = new StreamWriter("your path", false))
            {
                ser.Serialize(fs, emp);
            }

            var emp2 = ser.Deserialize(new StreamReader("your path"));
        }
    }

    public class Employee
    {
        [XmlElement(ElementName = "item1")]
        public Item Name { get; set; }`enter code here`

        [XmlElement(ElementName = "item2")]
        public Item Phone { get; set; }

        [XmlElement(ElementName = "item3")]
        public Item DOB { get; set; }

        [XmlElement(ElementName = "item4")]
        public Item Id { get; set; }
    }

    public class Item
    {
        public string Key { get; set; }
        public string Value { get; set; }
    }
}