You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在.NET Core中将特定结构XML反序列化为Person POCO模型?

在.NET Core中将name-value结构的XML反序列化为自定义POCO模型

问题场景

你调用Web服务得到了这种由<return>节点包裹name和value键值对的XML,自动生成的类和你想要的Person POCO结构不匹配,常规XML反序列化方法没法直接映射,下面给你两种实用的解决方案:

先回顾下你的输入信息:

原始XML

<returns>
  <return>
    <name>firstName</name>
    <value>John</value>
  </return>
  <return>
    <name>lastName</name>
    <value>Doe</value>
  </return>
  <return>
    <name>dateOfBirth</name>
    <value>01-01-1900 00:00</value>
  </return>
  <return>
    <name>address</name>
    <value>100, Example Street</value>
  </return>
</returns>

Visual Studio自动生成的类

// NOTE: Generated code may require at least .NET Framework 4.5 or .NET Core/Standard 2.0.
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class returns
{
    private returnsReturn[] returnField;
    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("return")]
    public returnsReturn[] @return { get { return this.returnField; } set { this.returnField = value; } }
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class returnsReturn
{
    private string nameField;
    private string valueField;
    /// <remarks/>
    public string name { get { return this.nameField; } set { this.nameField = value; } }
    /// <remarks/>
    public string value { get { return this.valueField; } set { this.valueField = value; } }
}

目标POCO

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string Address { get; set; }
}

方案一:中间类转换 + 手动映射(推荐新手使用)

这是最直观、成本最低的方法:先用自动生成的类完成XML到中间对象的反序列化,再把中间对象的键值对映射到Person类。优点是代码简单,容易理解和维护,适合字段数量不多的场景。

代码示例

using System.Xml.Serialization;
using System.IO;
using System.Linq;

// 假设xmlContent是你从Web服务获取的XML字符串
string xmlContent = "..."; 

// 1. 反序列化到自动生成的returns类
var serializer = new XmlSerializer(typeof(returns));
Person person;

using (var reader = new StringReader(xmlContent))
{
    var returnsObj = (returns)serializer.Deserialize(reader);
    
    // 2. 把returns里的键值对转成字典,方便映射
    var valueMap = returnsObj.@return.ToDictionary(item => item.name, item => item.value);
    
    // 3. 映射到Person对象
    person = new Person
    {
        FirstName = valueMap["firstName"],
        LastName = valueMap["lastName"],
        // 注意日期格式要和XML里的匹配,用ParseExact避免格式歧义
        DateOfBirth = DateTime.ParseExact(valueMap["dateOfBirth"], "dd-MM-yyyy HH:mm", null),
        Address = valueMap["address"]
    };
}

优化点:处理缺失字段

如果XML可能缺少某些字段,直接用valueMap["key"]会抛出KeyNotFoundException,建议改用TryGetValue做安全处理:

if (valueMap.TryGetValue("firstName", out var firstName))
{
    person.FirstName = firstName;
}
// 其他字段同理

方案二:自定义反序列化逻辑(直接映射到Person)

如果你想跳过中间类,直接把XML反序列化成Person,可以让Person类实现IXmlSerializable接口,手动控制XML的读取和写入逻辑。这种方法更灵活,适合需要频繁处理这种结构XML的场景。

实现IXmlSerializable的Person类

using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using System.Globalization;

public class Person : IXmlSerializable
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string Address { get; set; }

    // 这个方法返回null即可,无需额外实现
    public XmlSchema GetSchema() => null;

    // 核心:自定义XML读取逻辑
    public void ReadXml(XmlReader reader)
    {
        // 跳过根节点<returns>的开始标签
        reader.ReadStartElement("returns");
        
        var valueMap = new Dictionary<string, string>();
        
        // 遍历所有<return>节点
        while (reader.NodeType != XmlNodeType.EndElement || reader.Name != "returns")
        {
            if (reader.Name == "return" && reader.NodeType == XmlNodeType.Element)
            {
                reader.ReadStartElement("return");
                
                string fieldName = null;
                string fieldValue = null;
                
                // 读取当前<return>里的name和value
                while (reader.NodeType != XmlNodeType.EndElement || reader.Name != "return")
                {
                    if (reader.Name == "name")
                    {
                        fieldName = reader.ReadElementContentAsString();
                    }
                    else if (reader.Name == "value")
                    {
                        fieldValue = reader.ReadElementContentAsString();
                    }
                    else
                    {
                        // 跳过未知节点,避免解析失败
                        reader.Skip();
                    }
                }
                
                if (!string.IsNullOrEmpty(fieldName))
                {
                    valueMap[fieldName] = fieldValue;
                }
                
                // 跳过当前<return>的结束标签
                reader.ReadEndElement();
            }
            else
            {
                reader.Skip();
            }
        }
        
        // 把字典里的值映射到Person的属性
        if (valueMap.TryGetValue("firstName", out var firstName))
            FirstName = firstName;
        if (valueMap.TryGetValue("lastName", out var lastName))
            LastName = lastName;
        if (valueMap.TryGetValue("dateOfBirth", out var dobStr) 
            && DateTime.TryParseExact(dobStr, "dd-MM-yyyy HH:mm", CultureInfo.InvariantCulture, DateTimeStyles.None, out var dob))
            DateOfBirth = dob;
        if (valueMap.TryGetValue("address", out var address))
            Address = address;
        
        // 跳过根节点<returns>的结束标签
        reader.ReadEndElement();
    }

    // 如果需要把Person序列化成这种XML结构,可以实现这个方法
    public void WriteXml(XmlWriter writer)
    {
        writer.WriteStartElement("returns");
        
        WriteReturnNode(writer, "firstName", FirstName);
        WriteReturnNode(writer, "lastName", LastName);
        WriteReturnNode(writer, "dateOfBirth", DateOfBirth.ToString("dd-MM-yyyy HH:mm", CultureInfo.InvariantCulture));
        WriteReturnNode(writer, "address", Address);
        
        writer.WriteEndElement();
    }
    
    // 辅助方法:生成单个<return>节点
    private void WriteReturnNode(XmlWriter writer, string name, string value)
    {
        if (string.IsNullOrEmpty(value)) return;
        
        writer.WriteStartElement("return");
        writer.WriteElementString("name", name);
        writer.WriteElementString("value", value);
        writer.WriteEndElement();
    }
}

使用自定义类反序列化

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

string xmlContent = "...";
var serializer = new XmlSerializer(typeof(Person));
Person person;

using (var reader = new StringReader(xmlContent))
{
    person = (Person)serializer.Deserialize(reader);
}

内容的提问来源于stack exchange,提问作者adamasan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:59:12