XML元素反序列化失败求助:无法解析含ImportantNode的节点
XML反序列化问题:解析包含XmlElement集合的XML内容
我正尝试反序列化包含XmlElement集合的XML,需要解析<First>和<second>元素,其中<ImportantNode>内的内容是核心,<third>元素可以暂时忽略。目前卡在反序列化执行环节。
对应的XML内容
<configuration> <objects> <!-- this is a comment --> <First> <param name="Name" type="string">FirstName</param> <param name="Type" type="string">FirstType</param> <SomeElement> <SomeElement1> <param name="Name" type="string">AAA</param> <param name="Name2" type="string">BBB</param> </SomeElement1> </SomeElement> <param name="param1" type="string">1</param> <param name="param2" type="int">2</param> <param name="param3" type="float">3</param> <ImportantNode> <ImportantChildNode1> <param name="minValue" type="float">1</param> <param name="maxValue" type="float">100</param> </ImportantChildNode1> <ImportantChildNode2> <param name="minValue" type="float">1</param> <param name="maxValue" type="float">100</param> </ImportantChildNode2> <!-- 原XML此处为</IR>,是错误的,已修正 --> </ImportantNode> <elements> <element> <param name="paramName1" type="bool">true</param> </element> </elements> </First> <second> <param name="Name" type="string">2</param> <param name="Type" type="string">3</param> <ImportantNode> <ImportantChildNode1> <param name="minValue" type="float">2</param> <param name="maxValue" type="float">20</param> </ImportantChildNode1> <ImportantChildNode2> <param name="minValue" type="float">3</param> <param name="maxValue" type="float">30</param> </ImportantChildNode2> <!-- 原XML此处为</IR>,是错误的,已修正 --> </ImportantNode> </second> <third> <param name="Name" type="string">3</param> <param name="Type" type="string">4</param> <AAAA> <param name="DDD" type="string">XXX</param> </AAAA> <BBBB> <param name="DDD" type="string">ZZZ</param> </BBBB> <param name="Param1" type="string">6</param> <param name="Param2" type="string">301</param> </third> </objects> </configuration>
相关类定义
[Serializable] [XmlRoot(ElementName = "ImportantNode")] public class ImportantNode { [XmlElement(ElementName = "ImportantChildNode1")] public Param ImportantChildNode1Params { get; set; } [XmlElement(ElementName = "ImportantChildNode2")] public Param ImportantChildNode2Params { get; set; } } public class Param { [XmlAttribute(AttributeName = "name")] public string Name { get; set; } /* [XmlAttribute(AttributeName = "type")] public string type { get; set; }*/ [XmlText] public string Value { get; set; } } [Serializable] public class DeserializeObject { [XmlArrayItem("param")] public List<Param> Params { get; set; } [XmlElement (ElementName ="ImportantNode")] public ImportantNode ImportantNodeParams { get; set; } }
反序列化相关代码
IEnumerable<DeserializeObject> DeserializeObjectsList; XmlReaderSettings readSettings = new XmlReaderSettings(); readSettings.IgnoreComments = true; string filePath = "<xml file path>"; //using (XmlReader reader = XmlReader.Create(filePath, readSettings) XmlReader reader = XmlReader.Create(filePath, readSettings); XmlDocument filedoc = new XmlDocument(); filedoc.Load(reader/*filePath*/); //using var fileStream = new FileStream(filePath, FileMode.Open); XmlNodeList xmlNodeList = filedoc["configuration"].GetElementsByTagName("objects"); if (xmlNodeList == null) { throw new Exception("configuration file problem"); } DeserializeObject dObject = new DeserializeObject(); XmlSerializer serializer = new XmlSerializer(dObject.GetType()); var objects = xmlNodeList[0].ChildNodes; foreach (XmlElement object in objects) { var sElement = object.InnerXml; //string AAA = sElement.ToString(); StringReader SR = new StringReader(/*sElement.InnerXml*//*sElement*/object.OuterXml); var deserializedObject = serializer.Deserialize(SR); dObject = (DeserializeObject)serializer.Deserialize(SR); }
问题分析与修复方案
1. XML结构错误
原XML中<ImportantChildNode2>的闭合标签写成了</IR>,这会直接导致XML解析失败,必须修正为</ImportantChildNode2>。
2. 类属性标记不匹配
DeserializeObject的Params属性:原代码用[XmlArrayItem("param")],但XML中<param>是直接作为<First>/<second>的子元素,不是嵌套在数组节点里,应改为[XmlElement("param")]。ImportantNode的子节点类型:原代码中ImportantChildNode1Params和ImportantChildNode2Params类型是Param,但XML里每个<ImportantChildNode1>包含多个<param>,需要新增一个类来承载这些参数集合。
3. 反序列化逻辑错误
- 循环中两次调用
serializer.Deserialize(SR),第一次读取后流指针到末尾,第二次会返回null,需改为只调用一次。 - 未过滤
<third>元素和文本节点(换行、空格),需判断节点类型和名称后再处理。 - 未动态指定根节点名称:
<First>和<second>是不同的根元素,直接用DeserializeObject的类型会匹配失败,需创建指定根节点的XmlSerializer。
修复后的代码
修正后的类定义
[Serializable] [XmlRoot(ElementName = "ImportantNode")] public class ImportantNode { [XmlElement(ElementName = "ImportantChildNode1")] public ImportantChildNode ImportantChildNode1 { get; set; } [XmlElement(ElementName = "ImportantChildNode2")] public ImportantChildNode ImportantChildNode2 { get; set; } } // 新增类:承载每个ImportantChildNode下的param集合 public class ImportantChildNode { [XmlElement("param")] public List<Param> Params { get; set; } } public class Param { [XmlAttribute(AttributeName = "name")] public string Name { get; set; } [XmlAttribute(AttributeName = "type")] public string Type { get; set; } [XmlText] public string Value { get; set; } } [Serializable] public class DeserializeObject { [XmlElement("param")] public List<Param> Params { get; set; } [XmlElement(ElementName = "ImportantNode")] public ImportantNode ImportantNodeParams { get; set; } }
修正后的反序列化代码
List<DeserializeObject> deserializeObjectsList = new List<DeserializeObject>(); XmlReaderSettings readSettings = new XmlReaderSettings(); readSettings.IgnoreComments = true; string filePath = "<xml file path>"; using (XmlReader reader = XmlReader.Create(filePath, readSettings)) { XmlDocument filedoc = new XmlDocument(); filedoc.Load(reader); XmlNode objectsNode = filedoc.SelectSingleNode("//configuration/objects"); if (objectsNode == null) { throw new Exception("configuration file problem"); } foreach (XmlNode node in objectsNode.ChildNodes) { // 只处理First和second元素,跳过文本节点和third if (node.NodeType != XmlNodeType.Element || (node.Name != "First" && node.Name != "second")) continue; // 动态指定根节点名称,匹配当前元素的标签名 XmlSerializer serializer = new XmlSerializer(typeof(DeserializeObject), new XmlRootAttribute(node.Name)); using (StringReader sr = new StringReader(node.OuterXml)) { if (serializer.Deserialize(sr) is DeserializeObject deserializedObj) { deserializeObjectsList.Add(deserializedObj); } } } }
内容的提问来源于stack exchange,提问作者Guy E
相关产品推荐
相关产品推荐

