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

如何将XML元素值反序列化到C#自定义类的对应属性中

解决方案

有两种不需要手动逐个提取属性的实现方案,如下:

方案1:Linq to XML + 反射通用映射(无需修改现有Invoice类,推荐)

这个方案不需要给Invoice加任何特性或者接口适配,直接通过反射自动匹配属性名和XML里的name节点值,自动做类型转换:
首先要注意你提供的XML没有根节点,解析前需要先包裹一个根标签避免报错,完整代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;

// 你的原有Invoice类不需要任何修改
public class Invoice
{
    public string InvoiceId { get; set; }
    public string CompanyName { get; set; }
    public string VendorName { get; set; }
    public decimal GrossAmt { get; set; }
    public DateTime InvoiceDate { get; set; }
}

public static class XmlToInvoiceConverter
{
    public static List<Invoice> DeserializeInvoices(string xmlContent)
    {
        // 给原XML加根节点,否则无法解析
        var wrappedXml = $"<root>{xmlContent}</root>";
        var root = XElement.Parse(wrappedXml);
        var invoices = new List<Invoice>();

        // 取所有document节点
        foreach (var docNode in root.Elements("document"))
        {
            // 把当前document的所有属性转成字典,key是name节点值,value是value节点值
            var propDict = docNode.Element("propertyValues")
                .Elements("propertyValue")
                .ToDictionary(
                    p => p.Element("name").Value.Trim(),
                    p => p.Element("value").Value.Trim()
                );

            var invoice = new Invoice();
            var invoiceProps = typeof(Invoice).GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (var prop in invoiceProps)
            {
                // 忽略不可写的属性
                if (!prop.CanWrite) continue;
                // 匹配XML里的key,需严格大小写匹配可删除StringComparison.OrdinalIgnoreCase参数
                if (propDict.TryGetValue(prop.Name, StringComparison.OrdinalIgnoreCase, out var valueStr))
                {
                    // 做类型转换
                    object convertedValue = null;
                    if (prop.PropertyType == typeof(DateTime))
                    {
                        // 适配你的日期格式dd-MM-yyyy
                        convertedValue = DateTime.ParseExact(valueStr, "dd-MM-yyyy", null);
                    }
                    else
                    {
                        convertedValue = Convert.ChangeType(valueStr, prop.PropertyType);
                    }
                    prop.SetValue(invoice, convertedValue);
                }
            }
            invoices.Add(invoice);
        }
        return invoices;
    }
}

调用方法非常简单,直接把你原有的XML字符串传进去就能得到List<Invoice>结果。

方案2:实现IXmlSerializable接口,用原生XmlSerializer反序列化

如果你希望用系统自带的XmlSerializer标准流程,可以给Invoice类实现IXmlSerializable接口,代码如下:

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

[XmlRoot("document")]
public class Invoice : IXmlSerializable
{
    public string InvoiceId { get; set; }
    public string CompanyName { get; set; }
    public string VendorName { get; set; }
    public decimal GrossAmt { get; set; }
    public DateTime InvoiceDate { get; set; }

    public System.Xml.Schema.XmlSchema GetSchema() => null;

    public void ReadXml(XmlReader reader)
    {
        reader.ReadToFollowing("propertyValues");
        var propReader = reader.ReadSubtree();
        while (propReader.ReadToFollowing("propertyValue"))
        {
            var name = propReader.ReadElementContentAsString("name", "");
            var value = propReader.ReadElementContentAsString("value", "");
            
            switch (name)
            {
                case nameof(InvoiceId):
                    InvoiceId = value;
                    break;
                case nameof(CompanyName):
                    CompanyName = value;
                    break;
                case nameof(VendorName):
                    VendorName = value;
                    break;
                case nameof(GrossAmt):
                    GrossAmt = decimal.Parse(value);
                    break;
                case nameof(InvoiceDate):
                    InvoiceDate = DateTime.ParseExact(value, "dd-MM-yyyy", null);
                    break;
            }
        }
        reader.Read();
    }

    public void WriteXml(XmlWriter writer)
    {
        // 如果不需要序列化回XML可以留空
        throw new NotImplementedException();
    }
}

反序列化调用代码:

var serializer = new XmlSerializer(typeof(List<Invoice>), new XmlRootAttribute("root"));
var wrappedXml = $"<root>{yourOriginalXmlString}</root>";
using (var strReader = new StringReader(wrappedXml))
{
    var invoices = (List<Invoice>)serializer.Deserialize(strReader);
}

两种方案都可以满足需求,第一种通用型更强,后续如果Invoice加属性不需要修改转换逻辑,自动适配;第二种符合.NET XML序列化的标准规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 00:36:04