借助LINQ to XML实现XML中inv:code节点的批量替换需求
批量填充XML中的产品编码节点

我有一段时间未进行编程工作,目前在处理一个小型项目时遇到了问题:从某系统导出了发票XML文件,需要导入到另一系统中,但源系统未提供产品编码,仅保留了空的<inv:code />节点。计划编写WinForms C#工具,通过产品名称(如<inv:text>PPL doručení do Parcelshopu</inv:text>)在预定义字典中匹配正确的产品编码,将空的<inv:code />节点替换为<inv:code>S_PPL_M3</inv:code>。
XML结构
- 整个XML包含多个
<inv:invoice>节点 - 每个
<inv:invoice>包含一个<inv:invoiceDetail>节点 - 每个
<inv:invoiceDetail>包含多个<inv:invoiceItem>节点 - 每个
<inv:invoiceItem>包含一个<inv:text>节点和一个空的<inv:code />节点
需求步骤
- 获取单个
<inv:invoiceItem>节点 - 获取其子节点
<inv:text>的文本内容并保存到变量中 - 从预定义字典中匹配到对应的产品编码(此步骤已掌握)
- 在同一个
<inv:invoiceItem>节点内,将空的<inv:code />替换为<inv:code>正确编码</inv:code> - 遍历整个XML文件,批量完成上述替换操作
实现思路与代码示例
核心注意点
XML中的inv前缀对应实际命名空间URI,LINQ to XML处理带命名空间的节点必须通过XNamespace指定,不能直接使用前缀字符串。
完整代码
// 加载XML文件 XDocument? doc = XDocument.Load("源XML文件路径"); // 自动获取inv前缀对应的命名空间 XNamespace invNs = doc.Root.GetNamespaceOfPrefix("inv"); // 预定义产品名称与编码的映射字典 var productMapping = new Dictionary<string, string> { { "PPL doručení do Parcelshopu", "S_PPL_M3" }, // 添加其他产品的映射关系 }; // 遍历所有invoiceItem节点 foreach (var invoiceItem in doc.Descendants(invNs + "invoiceItem")) { // 获取当前item下的text节点 var textNode = invoiceItem.Element(invNs + "text"); if (textNode == null) continue; string productName = textNode.Value.Trim(); // 匹配产品编码 if (productMapping.TryGetValue(productName, out string productCode)) { // 获取当前item下的code节点 var codeNode = invoiceItem.Element(invNs + "code"); if (codeNode != null) { // 为code节点赋值,空节点会自动变为带内容的节点 codeNode.Value = productCode; } // 可选:如果code节点不存在,主动添加节点 // else invoiceItem.Add(new XElement(invNs + "code", productCode)); } } // 保存修改后的XML doc.Save("修改后的XML文件路径");
代码说明
- 命名空间处理:通过
doc.Root.GetNamespaceOfPrefix("inv")自动获取命名空间,避免硬编码URI导致的错误。 - 空值防护:增加节点存在性判断,避免空引用异常。
- 批量处理:通过
Descendants(invNs + "invoiceItem")一次性获取所有目标节点,遍历完成批量修改。
内容的提问来源于stack exchange,提问作者Antonin Sleis
相关产品推荐
相关产品推荐

