C#中如何仅替换XML文档里最后一处指定字符串值?
解决XML文档中仅替换最后一处指定字符串的问题
问题场景
有固定结构的XML文档(示例如下),需要仅将最后一处值为3023的字符串替换为2020,当前用Regex替换会修改所有匹配项,需要精准替换目标位置的内容。
XML示例文档
<cac:Party> <cbc:EndpointID schemeID="Country">3023</cbc:EndpointID> <cac:PartyIdentification> <cbc:ID schemeID="Country">3023</cbc:ID> </cac:PartyIdentification> <cac:PartyName> <cbc:Name>Test</cbc:Name> </cac:PartyName> <cac:PostalAddress> <cbc:AddressFormatCode listAgencyID="###" listID="urn:oioubl:codelist:addressformatcode-1.1">StructuredLax</cbc:AddressFormatCode> <cbc:StreetName>Test</cbc:StreetName> <cbc:CityName>Test</cbc:CityName> <cbc:PostalZone>Test</cbc:PostalZone> <cac:Country> <cbc:IdentificationCode>DK</cbc:IdentificationCode> </cac:Country> </cac:PostalAddress> <cac:PartyTaxScheme> <cbc:CompanyID schemeID="Country">3023</cbc:CompanyID> <cac:TaxScheme> <cbc:ID schemeID="urn:oioubl:id:taxschemeid-1.1" schemeAgencyID="320">63</cbc:ID> <cbc:Name>Moms</cbc:Name> </cac:TaxScheme> </cac:PartyTaxScheme> <cac:PartyLegalEntity> <cbc:RegistrationName>Test</cbc:RegistrationName> <cbc:CompanyID schemeID="Country">3023</cbc:CompanyID>
现有问题代码
当前使用StreamReader+StreamWriter+Regex的方式会替换所有3023:
string docText = null; using (StreamReader sr = new StreamReader(filename)) { docText = sr.ReadToEnd(); } Regex oldValue = new Regex("3023"); docText = oldValue.Replace(docText, "2020"); using (StreamWriter sw = new StreamWriter(filename)) { sw.Write(docText); }
可行实现方案
方案1:利用LastIndexOf精准定位最后一处匹配
直接找到最后一个3023的起始索引,通过字符串拼接完成替换:
string docText = null; using (StreamReader sr = new StreamReader(filename)) { docText = sr.ReadToEnd(); } string target = "3023"; string replacement = "2020"; int lastIndex = docText.LastIndexOf(target); if (lastIndex != -1) { docText = docText.Substring(0, lastIndex) + replacement + docText.Substring(lastIndex + target.Length); } using (StreamWriter sw = new StreamWriter(filename)) { sw.Write(docText); }
方案2:使用Regex替换最后一次匹配
通过MatchEvaluator结合计数器,仅替换最后一次匹配项:
string docText = null; using (StreamReader sr = new StreamReader(filename)) { docText = sr.ReadToEnd(); } string target = "3023"; string replacement = "2020"; int matchCount = Regex.Matches(docText, target).Count; int currentCount = 0; docText = Regex.Replace(docText, target, m => { currentCount++; return currentCount == matchCount ? replacement : m.Value; }); using (StreamWriter sw = new StreamWriter(filename)) { sw.Write(docText); }
方案3:解析XML节点精准修改(推荐)
因为处理的是XML文档,直接解析节点定位目标元素修改,避免字符串操作可能带来的格式问题:
using System.Xml.Linq; // 加载XML文档 XDocument doc = XDocument.Load(filename); // 定义XML命名空间(需与实际文档一致) XNamespace cac = "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"; XNamespace cbc = "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"; // 定位到目标节点:cac:PartyLegalEntity下的cbc:CompanyID var targetNode = doc.Descendants(cac + "PartyLegalEntity") .Elements(cbc + "CompanyID") .LastOrDefault(); if (targetNode != null && targetNode.Value == "3023") { targetNode.Value = "2020"; } // 保存修改后的文档 doc.Save(filename);
注意:需根据实际XML文档的命名空间调整代码中的URI,确保节点定位准确。
内容的提问来源于stack exchange,提问作者user1845777
相关产品推荐
相关产品推荐

