使用System.XML读取XML时RATED_CURRENT节点InnerText取值异常问题
问题描述
- 需求为基于
System.Xml实现XML参数读取逻辑:在FindCurrentParameters函数中加载指定路径的XML文件,遍历根节点下所有名为RATED_CURRENT的节点,匹配用户输入的额定电流值(例:输入1240);若节点值与输入值匹配,则读取该节点下所有子节点数据;遍历完成无匹配项时返回错误码CalibratorAverageErrorCode.CURRENT_NOT_FOUND,匹配成功返回CalibratorAverageErrorCode.NO_ERROR。 - 现有实现存在逻辑异常:直接读取
RATED_CURRENT节点的InnerText属性时,会将该节点下所有子节点的文本内容拼接为长字符串,无法正确获取RATED_CURRENT标签自身存储的额定电流值(即子节点前的数值,如48、76、1240等),导致值匹配逻辑失效,无法正确读取目标节点下的I_LINE_EST_A_SCALAR、SAMPLE_COUNT等子节点数据。
问题根因
RATED_CURRENT属于XML混合内容节点:节点本身直属存储额定电流文本值,同时嵌套了多个参数子元素。XmlNode.InnerText属性的默认逻辑是递归遍历当前节点下所有层级的子节点,拼接所有文本类型节点的内容返回,因此会把下属子节点的参数值全部拼接到额定电流字符串中,导致匹配失败。
正确实现方案
核心修正点:不要直接用InnerText取RATED_CURRENT的电流值,仅读取该节点直属的文本类型子节点的值作为匹配依据,匹配通过后再遍历读取下属元素类型子节点的参数。
基于XmlDocument的完整实现代码
using System; using System.IO; using System.Xml; using System.Globalization; public CalibratorAverageErrorCode FindCurrentParameters(string xmlFilePath, int targetRatedCurrent) { XmlDocument paramDoc = new XmlDocument(); try { paramDoc.Load(xmlFilePath); } catch (XmlException ex) { throw new InvalidDataException("XML文件格式损坏,无法加载", ex); } catch (FileNotFoundException ex) { throw new FileNotFoundException("指定路径的参数文件不存在", ex); } XmlNode rootNode = paramDoc.DocumentElement; if (rootNode == null) return CalibratorAverageErrorCode.CURRENT_NOT_FOUND; // 遍历根节点下所有RATED_CURRENT节点 XmlNodeList ratedCurrentNodes = rootNode.SelectNodes("RATED_CURRENT"); if (ratedCurrentNodes == null || ratedCurrentNodes.Count == 0) return CalibratorAverageErrorCode.CURRENT_NOT_FOUND; foreach (XmlNode currentNode in ratedCurrentNodes) { // 仅提取节点直属的文本值,不递归子节点 string ratedValueStr = string.Empty; foreach (XmlNode child in currentNode.ChildNodes) { if (child.NodeType == XmlNodeType.Text) { ratedValueStr = child.Value?.Trim() ?? string.Empty; break; } } // 额定电流值匹配 if (int.TryParse(ratedValueStr, NumberStyles.Integer, CultureInfo.InvariantCulture, out int ratedCurrent) && ratedCurrent == targetRatedCurrent) { // 匹配成功,遍历读取子节点参数 foreach (XmlNode paramNode in currentNode.ChildNodes) { // 跳过非元素节点,仅处理参数子标签 if (paramNode.NodeType != XmlNodeType.Element) continue; switch (paramNode.Name) { case "I_LINE_EST_A_SCALAR": if (double.TryParse(paramNode.InnerText.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out double scalarVal)) { // 此处替换为实际业务变量赋值逻辑 // CurrentCalibrateScalar = scalarVal; } break; case "SAMPLE_COUNT": if (int.TryParse(paramNode.InnerText.Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out int sampleVal)) { // 此处替换为实际业务变量赋值逻辑 // CalibrateSampleCount = sampleVal; } break; // 其余子参数按相同逻辑扩展即可 } } return CalibratorAverageErrorCode.NO_ERROR; } } // 所有节点遍历完成无匹配 return CalibratorAverageErrorCode.CURRENT_NOT_FOUND; } // 业务错误码定义示例 public enum CalibratorAverageErrorCode { NO_ERROR = 0, CURRENT_NOT_FOUND = 1002 }
补充说明
如果你使用System.Xml.Linq下的XDocumentAPI实现,逻辑完全一致:不要调用XElement.Value属性(该属性和InnerText逻辑相同,会递归拼接所有子节点文本),直接取节点的第一个节点判断是否为文本类型即可,核心取值代码如下:
XElement ratedCurrentElement = ...; // 目标RATED_CURRENT节点 if (ratedCurrentElement.FirstNode is XText textNode) { string ratedValueStr = textNode.Value.Trim(); // 后续数值匹配逻辑和上述实现一致 }
内容的提问来源于stack exchange,提问作者Jorge Jurado-Garcia
相关产品推荐
相关产品推荐

