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

如何将XML中无分组的md_*标签反序列化为嵌套对象?

解决XmlSerializer将同级XML元素映射到嵌套DTO属性的问题

你遇到的核心问题很明确:XML里的<md_nr>、<md_mart_id>、<md_mtyp_nr>是根节点<treffer>的直接子元素,但你想把它们封装到DeAnalyseArtikelXmlDto的Medium属性里,之前给Medium标注[XmlElement("treffer")]完全不生效——这是因为你的XML里根本不存在嵌套的<treffer>子节点,这个特性是告诉序列化器去寻找名为treffer的子元素来映射Medium,自然找不到目标内容。

下面是两种可行的解决方案:

方案1:通过代理属性桥接(逻辑直观)

在DeAnalyseArtikelXmlDto中为三个XML元素创建代理属性,将值传递给内部的Medium对象,同时标记Medium为[XmlIgnore]避免序列化器直接处理它:

[XmlRoot("treffer")]
public class DeAnalyseArtikelXmlDto {
    [XmlElement("prod_internid")]
    public long ArtikelId { get; set; }

    // 忽略直接序列化Medium,通过代理属性完成XML映射
    [XmlIgnore]
    public DeMedienXmlDto Medium { get; set; } = new DeMedienXmlDto();

    // 代理<md_nr>元素,映射到Medium.MedienNr
    [XmlElement("md_nr")]
    public int MedienNrProxy {
        get => Medium.MedienNr;
        set => Medium.MedienNr = value;
    }

    // 代理<md_mart_id>元素,映射到Medium.MedienArtId
    [XmlElement("md_mart_id")]
    public int MedienArtIdProxy {
        get => Medium.MedienArtId;
        set => Medium.MedienArtId = value;
    }

    // 代理<md_mtyp_nr>元素,映射到Medium.MedienTypId
    [XmlElement("md_mtyp_nr")]
    public string MedienTypIdProxy {
        get => Medium.MedienTypId;
        set => Medium.MedienTypId = value;
    }

    [XmlElement("mra_th")]
    public List<DeThemenXmlDto> Themen { get; set; }
}

// 保持原DeMedienXmlDto结构不变
public class DeMedienXmlDto {
    [XmlElement("md_nr")]
    public int MedienNr { get; set; }
    [XmlElement("md_mart_id")]
    public int MedienArtId { get; set; }
    [XmlElement("md_mtyp_nr")]
    public string MedienTypId { get; set; }
}

这种方法逻辑清晰,不需要大幅修改原有DTO结构,代理属性只负责完成XML和内部对象的桥接工作。

方案2:直接绑定嵌套属性(代码更简洁)

如果你不想添加代理属性,可以直接在DeAnalyseArtikelXmlDto中用XmlElement特性将XML元素绑定到Medium的属性上,同时调整DeMedienXmlDto的特性避免冲突:

[XmlRoot("treffer")]
public class DeAnalyseArtikelXmlDto {
    [XmlElement("prod_internid")]
    public long ArtikelId { get; set; }

    // 无需额外特性,通过下方属性完成映射
    public DeMedienXmlDto Medium { get; set; } = new DeMedienXmlDto();

    [XmlElement("md_nr")]
    public int MedienNr {
        get => Medium.MedienNr;
        set => Medium.MedienNr = value;
    }

    [XmlElement("md_mart_id")]
    public int MedienArtId {
        get => Medium.MedienArtId;
        set => Medium.MedienArtId = value;
    }

    [XmlElement("md_mtyp_nr")]
    public string MedienTypId {
        get => Medium.MedienTypId;
        set => Medium.MedienTypId = value;
    }

    [XmlElement("mra_th")]
    public List<DeThemenXmlDto> Themen { get; set; }
}

// 移除XmlElement特性,避免和父类的映射冲突
public class DeMedienXmlDto {
    public int MedienNr { get; set; }
    public int MedienArtId { get; set; }
    public string MedienTypId { get; set; }
}

这种方式和方案1本质逻辑一致,但去掉了代理属性的后缀,代码更简洁,适合追求精简结构的场景。

为什么原方法不生效?

你之前给Medium标注[XmlElement("treffer")],是告诉XmlSerializer:在当前节点下寻找一个名为treffer的子元素,将其反序列化为Medium对象。但你的XML结构中,根节点就是<treffer>,里面的<md_nr>等是直接子元素,根本没有嵌套的<treffer>子节点,所以序列化器找不到对应元素,Medium自然无法被赋值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:08:11