如何将XML中无分组的md_*标签反序列化为嵌套对象?
你遇到的核心问题很明确: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

