XML反序列化为DTO时DeMedienArtXmlDto属性为空的问题排查
你遇到的问题主要来自两个核心问题:嵌套DTO的XML注解错误,以及序列化器无法自动将平级XML元素映射到嵌套对象。咱们一步步拆解解决:
1. 修正嵌套DTO的注解错误
你给DeMedienArtXmlDto添加了[XmlRoot("treffer")]注解,但这个类根本不是XML的根节点(根节点是<treffer>,对应DeAnalyseArtikelXmlDto)。这个错误注解会直接干扰XmlSerializer的解析逻辑,导致嵌套属性无法被识别。
先移除这个错误注解,并补充md_mart_id的映射(XML里有这个元素但你之前没处理):
// 移除[XmlRoot("treffer")],这个类是嵌套对象,不是根节点 public class DeMedienArtXmlDto { [XmlElement("md_mart_id")] public int Id { get; set; } [XmlElement("md_mart_bez")] public string Bezeichnung { get; set; } }
2. 解决平级元素到嵌套对象的映射问题
你的XML结构里,<md_mart_id>和<md_mart_bez>是<treffer>的直接子元素,而非某个<MedienArt>子节点的内容。默认的XmlSerializer不会自动把这些平级元素归到你的MedienArt嵌套属性里——它不知道这些元素属于这个对象。
这里有两种简单的解决方式:
方式一:通过中间属性映射(推荐)
在父DTO里添加对应XML元素的中间属性,再通过一个忽略序列化的计算属性封装成嵌套对象:
[XmlRoot("treffer")] public class DeAnalyseArtikelXmlDto { [XmlElement("prod_internid")] public long ArtikelId { get; set; } [XmlElement("md_nr")] public int MedienNr { get; set; } // 映射XML里的md_mart_id [XmlElement("md_mart_id")] private int _medienArtId { get; set; } // 映射XML里的md_mart_bez [XmlElement("md_mart_bez")] private string _medienArtBezeichnung { get; set; } // 用XmlIgnore标记,告诉序列化器不处理这个属性 [XmlIgnore] public DeMedienArtXmlDto MedienArt { get => new DeMedienArtXmlDto { Id = _medienArtId, Bezeichnung = _medienArtBezeichnung }; set { _medienArtId = value.Id; _medienArtBezeichnung = value.Bezeichnung; } } }
方式二:自定义XML序列化(复杂场景适用)
如果你的嵌套对象逻辑更复杂,可以实现IXmlSerializable接口手动控制序列化/反序列化流程,但这种方式代码量更大,适合需要高度定制的场景。
3. 额外提醒:XML编码问题
你的XML声明是encoding="UTF-16",但你用StreamReader读取时没有指定编码,默认会用UTF-8解析,这可能导致乱码或读取失败。建议修改读取代码:
// 使用Encoding.Unicode(对应UTF-16)读取文件 StreamReader xmlStream = new StreamReader(XmlFilename, Encoding.Unicode);
这样修改后,你的MedienArt属性就能正确获取到<md_mart_id>和<md_mart_bez>的值了。
内容的提问来源于stack exchange,提问作者xeraphim

