XmlSerializer序列化List<T>节点嵌套问题及解决方案咨询
问题描述
使用XmlSerializer将C#类对象导出为XML时,序列化List<T>属性出现同名节点嵌套的问题。
测试类结构如下:
public class PmtInf { public string PmtInfId = "PAYMENT REFERENCE";//Referencia de pago public string PmtMtd = "TRF"; public PmtTpInf PmtTpInf = new PmtTpInf(); public string ReqdExctnDt = "2020-06-24";//Fecha de pago public Dbtr Dbtr = new Dbtr(); public InitgPty DbtrAcct = new InitgPty(); // 问题属性 public List<CdtTrfTxInf> CdtTrfTxInf = new List<CdtTrfTxInf>() { new CdtTrfTxInf(), new CdtTrfTxInf() }; } public class CdtTrfTxInf { public PmtId PmtId = new PmtId(); public Amt Amt = new Amt(); public CdtrAgt CdtrAgt = new CdtrAgt(); public Dbtr Cdtr = new Dbtr(); public InitgPty CdtrAcct = new InitgPty(); }
序列化代码:
var XML = new System.Xml.Serialization.XmlSerializer(Objeto.GetType()); var Path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "//XMLExport.xml"; // 原代码缺少+号,需修正 FileStream file = File.Create(Path); XML.Serialize(file, Objeto); file.Close();
当前生成的XML中,<CdtTrfTxInf>节点出现嵌套:
<PmtInf> <PmtInfId>PAYMENT REFERENCE</PmtInfId> <PmtMtd>TRF</PmtMtd> <PmtTpInf> </PmtTpInf> <ReqdExctnDt>2020-06-24</ReqdExctnDt> <Dbtr> </Dbtr> <DbtrAcct> </DbtrAcct> <!-- 问题:外层<CdtTrfTxInf>包裹了子节点 --> <CdtTrfTxInf> <CdtTrfTxInf> more.... </CdtTrfTxInf> <CdtTrfTxInf> more.... </CdtTrfTxInf> </CdtTrfTxInf> </PmtInf>
期望的XML结构是在<PmtInf>下直接生成多个同级<CdtTrfTxInf>节点:
<PmtInf> <PmtInfId>PAYMENT REFERENCE</PmtInfId> <PmtMtd>TRF</PmtMtd> <PmtTpInf> </PmtTpInf> <ReqdExctnDt>2020-06-24</ReqdExctnDt> <Dbtr> </Dbtr> <DbtrAcct> </DbtrAcct> <CdtTrfTxInf> more.... </CdtTrfTxInf> <CdtTrfTxInf> more.... </CdtTrfTxInf> </PmtInf>
解决方案
问题根源是XmlSerializer默认会为List<T>类型生成一个与属性/字段同名的外层包裹节点,再在内部生成与元素类型同名的子节点。由于你的List字段名和元素类型名都是CdtTrfTxInf,就出现了嵌套的同名节点。
只需两步修改即可解决:
- 将公共字段改为属性(
XmlSerializer更推荐使用属性进行序列化,特性也更易管控) - 为List属性添加
[XmlElement]特性,指定每个元素的节点名称,让序列化器直接输出同级节点,不生成外层包裹节点
修改后的PmtInf类代码:
using System.Xml.Serialization; // 需引用此命名空间 public class PmtInf { public string PmtInfId { get; set; } = "PAYMENT REFERENCE";//Referencia de pago public string PmtMtd { get; set; } = "TRF"; public PmtTpInf PmtTpInf { get; set; } = new PmtTpInf(); public string ReqdExctnDt { get; set; } = "2020-06-24";//Fecha de pago public Dbtr Dbtr { get; set; } = new Dbtr(); public InitgPty DbtrAcct { get; set; } = new InitgPty(); // 添加XmlElement特性,指定节点名,去掉外层包裹 [XmlElement("CdtTrfTxInf")] public List<CdtTrfTxInf> CdtTrfTxInf { get; set; } = new List<CdtTrfTxInf>() { new CdtTrfTxInf(), new CdtTrfTxInf() }; }
同时修正序列化代码中的路径拼接错误(原代码缺少+号):
var Path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "//XMLExport.xml";
这样修改后,序列化生成的XML就会直接在<PmtInf>节点下生成多个同级的<CdtTrfTxInf>节点,符合需求。
内容的提问来源于stack exchange,提问作者Jonathan Jimenez
相关产品推荐
相关产品推荐

