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

从流反序列化XML到List<T>时触发异常,请求排查

问题原因与解决方案

这个异常的核心原因是你的XML结构和序列化器的期望不匹配,具体来说有两个关键问题:


1. 模型类的XML属性标注错误

你把[XmlRoot("invoices")]加在了Invoice类上,但实际上:

  • <invoices>是整个XML的根节点,包含多个<invoice>子节点
  • Invoice类应该对应单个<invoice>子节点,而不是根节点

这个错误标注会让序列化器混淆节点的层级关系。

2. 直接序列化List<Invoice>的默认行为不符合你的XML结构

当你使用XmlSerializer(typeof(List<Invoice>))时,序列化器默认会期望根节点是<ArrayOfInvoice>(这是.NET对集合类型序列化的默认命名规则),但你的XML根节点是<invoices>,两者不匹配,这就是抛出" was not expected."异常的直接原因。


修正后的完整代码

第一步:调整模型类,增加根节点包装类

我们需要一个专门的类来对应<invoices>根节点,然后在这个类里包含一个对应所有<invoice>子节点的集合:

// 对应单个<invoice>子节点
public class Invoice
{
    [XmlElement(ElementName = "description", IsNullable = true)]
    public string Description { get; set; }

    [XmlElement(ElementName = "invoice_date")]
    public string InvoiceDate { get; set; }

    [XmlElement(ElementName = "invoice_number")]
    public string InvoiceNumber { get; set; }

    [XmlElement(ElementName = "date_due")]
    public string DateDue { get; set; }

    [XmlElement(ElementName = "amount")]
    public string Amount { get; set; }
}

// 对应根节点<invoices>
[XmlRoot("invoices")]
public class InvoicesWrapper
{
    // 用[XmlElement("invoice")]指定每个子节点的名称为<invoice>
    [XmlElement("invoice")]
    public List<Invoice> Invoices { get; set; } = new List<Invoice>();
}

第二步:修改反序列化方法

现在序列化器需要针对InvoicesWrapper类来创建,反序列化后再取出里面的Invoice集合:

public List<Invoice> ParseRecords(Stream stream)
{
    List<Invoice> invoices = new List<Invoice>();
    try
    {
        stream.Position = 0;
        // 改为序列化InvoicesWrapper类型
        XmlSerializer serializer = new XmlSerializer(typeof(InvoicesWrapper));
        var wrapper = (InvoicesWrapper)serializer.Deserialize(stream);
        invoices = wrapper.Invoices;
    }
    catch (Exception ex)
    {
        log.Error(ex);
    }
    return invoices;
}

为什么这样能解决问题?

  • 包装类InvoicesWrapper的[XmlRoot("invoices")]告诉序列化器:根节点的名称是<invoices>,和你的XML结构完全匹配
  • [XmlElement("invoice")]指定集合中的每个元素对应XML里的<invoice>子节点,这样序列化器就能正确把每个子节点映射到Invoice对象
  • 不再直接序列化List<Invoice>,避免了默认的<ArrayOfInvoice>根节点不匹配的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:16:37