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

如何在C#中反序列化含同名不同类型元素的XML?

用单个C#类兼容两种XML结构的反序列化方案

你遇到的问题很典型——同一个API返回两种不同结构的XML,却想用同一个模型类来处理。核心问题在于<foo>节点的两种形态:一种是直接包含文本内容,另一种是包含子元素。下面是能完美解决这个问题的方案:

核心思路

我们需要让Foo类同时支持两种情况:

  • 当<foo>是纯文本节点时,捕获其文本内容
  • 当<foo>包含子元素时,反序列化这些子元素

可以通过[XmlText]属性实现文本内容的捕获,同时保留子元素的序列化配置。另外要注意你之前的代码误用了[XmlAttribute]——foos和foo的子节点都是XML元素,不是属性,应该用[XmlArray]/[XmlArrayItem]来配置集合映射。

完整代码实现

using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;

[XmlRoot("root")]
public class Root
{
    // 用XmlArray和XmlArrayItem正确映射<foos>下的<foo>集合
    [XmlArray("foos")]
    [XmlArrayItem("foo")]
    public List<Foo> Foos { get; set; } = new List<Foo>();
}

public class Foo
{
    // 捕获<foo>节点的直接文本内容
    [XmlText]
    public string TextContent { get; set; }

    // 映射<foo>下的子元素
    [XmlElement("fooName")]
    public string FooName { get; set; }

    [XmlElement("fooId")]
    public string FooId { get; set; }

    [XmlElement("fooDate")]
    public string FooDate { get; set; }
}

// 反序列化方法(和你原逻辑一致)
private Root Deserialize(string xmlData)
{
    var serializer = new XmlSerializer(typeof(Root));
    using (var reader = new StringReader(xmlData))
    {
        return (Root)serializer.Deserialize(reader);
    }
}

效果说明

  • 对于Type 1的XML,每个Foo对象的TextContent会被赋值为"some"、"text"、"here",而FooName/FooId/FooDate会是null
  • 对于Type 2的XML,每个Foo对象的FooName/FooId/FooDate会被正确赋值,TextContent会是null(因为<foo>节点没有直接文本内容)

你可以根据业务逻辑,在使用时判断TextContent是否为空,来区分两种情况进行后续处理。

为什么之前的方案不行?

  1. 第一种方案用[XmlAttribute(AttributeName = "foos")]是错误的——foos是XML元素,不是根节点的属性,无法正确映射集合
  2. 第二种方案的Foo类没有处理纯文本节点的逻辑,遇到Type 1的XML时,没有对应的属性捕获文本内容,导致反序列化失败

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:36:50