C#操作XML:如何查找指定InnerText节点并在对应位置插入数据
问题根因
代码无法定位目标节点是两个明确的错误导致的:
- XPath查询路径错误:
ClientFile.SelectNodes("MachineName")仅匹配XML根节点下的直接子节点,但你的MachineName节点嵌套在/Root/MachineProfile/路径下,查询路径不匹配,返回的节点列表始终为空。 - 节点值匹配逻辑错误:调用
Node.ToString()返回的是XmlNode对象的类型字符串(如System.Xml.XmlElement),并非节点存储的设备名称文本,即使查到节点也无法完成匹配。
实现方案
不需要遍历所有MachineName节点,直接通过XPath条件查询一步定位到对应设备的MachineProfile父节点(即数据插入的目标位置),再创建子节点写入测量数据即可。
- 节点定位:使用XPath语句
//MachineProfile[MachineName='设备名'],直接筛选出子节点MachineName文本匹配选中设备的MachineProfile节点,无需额外遍历。 - 数据插入:定位到目标节点后,通过
CreateElement方法创建对应测量项的子节点,将自定义类XmlMachineMeasurement的属性值赋值给节点的InnerText,追加到目标节点下,最后保存文件即可。
完整修正代码
// 确保该自定义类实例的作用域可在点击事件中访问 XmlMachineMeasurement NewMachineMeasurement = new XmlMachineMeasurement(); private void btnDone_Click(object sender, EventArgs e) { // 空值校验,避免未选中项时报错 if (cmbMachineName.SelectedItem == null) { MessageBox.Show("请先选择目标设备"); return; } string SelectedMachine = cmbMachineName.SelectedItem.ToString(); XmlDocument ClientFile = new XmlDocument(); ClientFile.Load(frmMain.ClientFileName); // 核心:直接定位匹配设备名的MachineProfile节点 XmlNode targetMachineNode = ClientFile.SelectSingleNode( $"//MachineProfile[MachineName='{SelectedMachine}']" ); if (targetMachineNode == null) { MessageBox.Show($"未找到名称为{SelectedMachine}的设备节点"); return; } // 创建测量数据的容器节点,也可直接将测量项追加到MachineProfile下 XmlElement measurementRoot = ClientFile.CreateElement("MeasurementRecord"); // 逐个写入测量属性 XmlElement dateNode = ClientFile.CreateElement("MeasurementDate"); dateNode.InnerText = NewMachineMeasurement.MeasurementDate; measurementRoot.AppendChild(dateNode); XmlElement rmsHdeNode = ClientFile.CreateElement("RMShorDE"); rmsHdeNode.InnerText = NewMachineMeasurement.RMShorDE; measurementRoot.AppendChild(rmsHdeNode); XmlElement rmsVdeNode = ClientFile.CreateElement("RMSvertDE"); rmsVdeNode.InnerText = NewMachineMeasurement.RMSvertDE; measurementRoot.AppendChild(rmsVdeNode); XmlElement rmsAdeNode = ClientFile.CreateElement("RMSaxDE"); rmsAdeNode.InnerText = NewMachineMeasurement.RMSaxDE; measurementRoot.AppendChild(rmsAdeNode); XmlElement rmsHndeNode = ClientFile.CreateElement("RMShorNDE"); rmsHndeNode.InnerText = NewMachineMeasurement.RMShorNDE; measurementRoot.AppendChild(rmsHndeNode); XmlElement rmsVndeNode = ClientFile.CreateElement("RMSvertNDE"); rmsVndeNode.InnerText = NewMachineMeasurement.RMSvertNDE; measurementRoot.AppendChild(rmsVndeNode); XmlElement rmsAndeNode = ClientFile.CreateElement("RMSaxNDE"); rmsAndeNode.InnerText = NewMachineMeasurement.RMSaxNDE; measurementRoot.AppendChild(rmsAndeNode); // 将组装好的测量数据追加到目标设备节点下 targetMachineNode.AppendChild(measurementRoot); // 保存修改到磁盘文件 ClientFile.Save(frmMain.ClientFileName); MessageBox.Show("测量数据写入完成"); }
补充说明
- 如果不需要单独的
MeasurementRecord节点做数据归类,可以直接把各个测量属性节点追加到targetMachineNode下,不影响数据结构。 - 如果设备名可能包含单引号等特殊字符,直接拼接XPath会出现语法错误,可改用遍历方式匹配节点,避免异常:
XmlNode targetMachineNode = null; foreach(XmlNode profileNode in ClientFile.SelectNodes("//MachineProfile")) { XmlNode nameNode = profileNode.SelectSingleNode("MachineName"); if (nameNode != null && nameNode.InnerText.Trim() == SelectedMachine.Trim()) { targetMachineNode = profileNode; break; } }
- 所有对XmlDocument的修改都保存在内存中,必须调用
Save()方法才会写入到实际文件。
内容的提问来源于stack exchange,提问作者ElectricRay81
相关产品推荐
相关产品推荐

