用特定捕获组上的操作替换正则表达式的所有匹配项

时间:2014-05-06 07:57:30

标签: c# regex

我有不同的Xml字符串,可以包含以下格式的一个或多个部分:

<ns1:AcctId>47862656</ns1:AcctId>

中间的值可以改变。我想用操纵值替换此<ns:1:AcctId>元素的所有出现(从BBAN到IBAN是特定的)。

我在XMLModel类中使用属​​性Xml(XML字符串)进行了以下方法:

string regexString = "(<ns1:AcctId>)(?<AcctId>.*?)(</ns1:AcctId>)";
Regex regex = new Regex(regexString);
Match match = regex.Match(Xml);
string AcctId = match.Groups["AcctId"].Value;
string IBANizedAcctId = IBANHelper.ConvertBBANToIBAN(AcctId);

Xml = Regex.Replace(Xml, regexString, string.Format("$1{0}$3", IBANizedAcctId));

这里的想法是regexString有三个捕获组,我将中间值(帐号)替换为转换为IBAN的帐号。

不幸的是,此代码不起作用:1)它确实捕获AcctId的值,但它没有正确替换它,因为它丢失了最后</ns1:AcctId>部分。 2)它将匹配的所有出现替换为第一个中捕获的值,而它应该用捕获的特定值替换每个出现的值。

有没有办法在C#中这样做?如果是这样,有人可以给我一些关于如何做到这一点的指示吗?任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

你不应该使用正则表达式来操纵XML,它们不是适合它的工具,并且不会一直工作。例如,XML文件可以使用除ns1以外的名称空间前缀,映射到同一名称空间,并且它在语义上是等效的,但是你的正则表达式不再起作用。

您应该使用XML解析器;最容易使用的是Linq to XML:

var doc = XDocument.Parse(Xml);
var ns1 = XNamespace.Get("http://TheNamespaceMappedToTheNs1Prefix");
var elements = doc.Descendants(ns1 + "AcctId");
foreach (var e in elements)
{
    e.Value = IBANHelper.ConvertBBANToIBAN(e.Value); 
}
Xml = doc.ToString();

答案 1 :(得分:1)

除了通常不使用正则表达式来操纵XML。

string regex = "(?<=<ns1:AcctId>).*?(?=</ns1:AcctId>)";
Xml = Regex.Replace(Xml, regex, delegate(Match m) {
                           return IBANHelper.ConvertBBANToIBAN(m.Value);
                         });

这使用积极向前看并向后看,以便匹配只是帐号,然后重载到Regex.Replace接受匹配评估。