如何反序列化带不同type属性的XML数组并解决i:type属性报错问题
问题根源
报错由两个核心配置错误导致:
- 数组节点名称配置错误:XML中的节点名
_x003C_CustomizationsForTypeList_x003E_k__BackingField是<CustomizationsForTypeList>k__BackingField的XML编码形式,XmlArrayAttribute需要填写编码后的实际节点名,而不是原始的自动属性 backing field 名称。 - 派生类XmlType命名空间配置错误:
i:type属性的取值对应的类型名称,所属命名空间是根节点的Dynamics AX业务命名空间,不是http://www.w3.org/2001/XMLSchema-instance(这个只是xsi:type属性本身的命名空间,和类型所属命名空间无关)。
修正后的类定义
[XmlRoot(Namespace = "http://schemas.datacontract.org/2004/07/Microsoft.Dynamics.AX.Security.Management")] public class SecurityCustomizationData { // 填写XML中实际存在的编码后的节点名 [XmlArray("_x003C_CustomizationsForTypeList_x003E_k__BackingField")] [XmlArrayItem("BaseRepositoryCustomizations", Type = typeof(RoleRepoCust))] [XmlArrayItem("BaseRepositoryCustomizations", Type = typeof(DutyRepoCust))] [XmlArrayItem("BaseRepositoryCustomizations", Type = typeof(PrivilegeRepoCust))] public BaseRepositoryCustomizations[] CustomizationsForTypeList { get; set; } } public class BaseRepositoryCustomizations { } // 命名空间替换为根节点的业务命名空间 [XmlType(TypeName = "RepositoryCustomizationsOfAxSecurityRoleNcCATIYq", Namespace = "http://schemas.datacontract.org/2004/07/Microsoft.Dynamics.AX.Security.Management")] public class RoleRepoCust : BaseRepositoryCustomizations { } [XmlType(TypeName = "RepositoryCustomizationsOfAxSecurityDutyNcCATIYq", Namespace = "http://schemas.datacontract.org/2004/07/Microsoft.Dynamics.AX.Security.Management")] public class DutyRepoCust : BaseRepositoryCustomizations { } [XmlType(TypeName = "RepositoryCustomizationsOfAxSecurityPrivilegeNcCATIYq", Namespace = "http://schemas.datacontract.org/2004/07/Microsoft.Dynamics.AX.Security.Management")] public class PrivilegeRepoCust : BaseRepositoryCustomizations { }
验证反序列化&序列化代码
// 反序列化 var serializer = new XmlSerializer(typeof(SecurityCustomizationData)); using var reader = new StringReader("你的XML内容字符串"); var result = (SecurityCustomizationData)serializer.Deserialize(reader); // 序列化回XML可自动生成正确的i:type属性 using var writer = new StringWriter(); serializer.Serialize(writer, result); var xmlOutput = writer.ToString();
补充说明
如果不需要保留原始的backing field节点名,后续序列化时输出更整洁的XML,可以给XmlArrayAttribute配置ElementName为自定义的名称比如CustomizationsForTypeList,只要和你实际需要的输出格式匹配即可。
内容的提问来源于stack exchange,提问作者Kempeth
相关产品推荐
相关产品推荐

