如何将元素名称不同但结构一致的XML反序列化为C#对象?
解决XML元素名含固定子串的反序列化问题
当需要反序列化的多个XML结构一致,但同含义的元素名称仅包含固定子串(如都带"Test"、"Name")时,XmlSerializer因为依赖精确的元素名称匹配,无法通过特性配置(如通配符、多ElementName)实现匹配,这时候改用LINQ to XML是更灵活的方案。
实现步骤
1. 保留原有实体类
原有的C#实体类无需修改,继续使用:
[XmlRoot(ElementName = "MainFile", IsNullable = true)] public class FileAsXML { public Test Test { get; set; } } public class Test { public string Name { get; set; } public HelloFriend HelloFriend { get; set; } } // 假设HelloFriend的定义如下(可根据实际XML结构调整) public class HelloFriend { // 示例属性,根据实际XML节点定义 public string Content { get; set; } }
2. 使用LINQ to XML手动映射
通过XDocument加载XML,然后基于元素名称包含指定子串来定位节点,手动构建实体对象:
private FileAsXML GetDataObject(string xml) { var doc = XDocument.Parse(xml); var result = new FileAsXML(); // 找到MainFile下名称包含"Test"的子元素 var testElement = doc.Root.Elements().FirstOrDefault(e => e.Name.LocalName.Contains("Test")); if (testElement != null) { var testObj = new Test(); // 找到Test节点下名称包含"Name"的子元素,获取文本值 var nameElement = testElement.Elements().FirstOrDefault(e => e.Name.LocalName.Contains("Name")); if (nameElement != null) { testObj.Name = nameElement.Value; } // 找到Test节点下名称包含"HelloFriend"的子元素,映射到HelloFriend对象 var helloFriendElement = testElement.Elements().FirstOrDefault(e => e.Name.LocalName.Contains("HelloFriend")); if (helloFriendElement != null) { testObj.HelloFriend = new HelloFriend { Content = helloFriendElement.Value // 若HelloFriend有子节点,可继续递归处理 }; } result.Test = testObj; } return result; }
3. 关键点说明
- 使用
XDocument.Parse加载XML字符串(若从文件读取,改用XDocument.Load) - 通过
Elements()遍历子节点,结合Contains()匹配元素名称中的固定子串 - 若存在多个匹配节点,可根据需求将
FirstOrDefault替换为Where后批量处理 - 针对复杂嵌套结构,可封装递归方法统一处理子节点映射
内容的提问来源于stack exchange,提问作者Mateusz Duda
相关产品推荐
相关产品推荐

