You need to replace character patterns within the target string with a new string. However, in this case, each replacement operation has a unique set of conditions that must be satisfied in order to allow the replacement to occur. Consider, for example, that you receive a string in the form of XML (or possibly HTML). You wish to modify an attribute of a specific XML tag to a particular number, but only if that number is within a specified range (or possibly outside of a particular range).
Use
the overloaded instance Replace
method that
accepts a MatchEvaluator
delegate along with its
other parameters. The MatchEvaluator
delegate,
which is a callback method that overrides the default behavior of the
Replace
method, is shown
here:
using System; using System.Text.RegularExpressions; public static string MatchHandler(Match theMatch) { // Handle Top property of the Property tag if (theMatch.Value.StartsWith("<Property")) { long topPropertyValue = 0; // Obtain the numeric value of the Top property Match topPropertyMatch = Regex.Match(theMatch.Value, "Top="([-]*\d*)"); if (topPropertyMatch.Success) { if (topPropertyMatch.Groups[1].Value.Trim( ).Equals("")) { // If blank, set to zero return (theMatch.Value.Replace("Top=""", "Top="0"")); } else if (topPropertyMatch.Groups[1].Value.Trim( ).Equals("-")) { // If only a negative sign (syntax error), set to zero return (theMatch.Value.Replace("Top="-"", "Top="0"")); } else { // We have a valid number // Convert the matched string to a numeric value topPropertyValue = long.Parse( topPropertyMatch.Groups[1].Value, System.Globalization.NumberStyles.Any); // If the Top property is out of the specified // range, set it to zero if (topPropertyValue < 0 || topPropertyValue > 5000) { return (theMatch.Value.Replace("Top="" + topPropertyValue + """, "Top="0"")); } } } } return (theMatch.Value); }
The callback method for the Replace
method is
shown here:
public static void ComplexReplace(string matchPattern, string source) { MatchEvaluator replaceCallback = new MatchEvaluator(MatchHandler); Regex RE = new Regex(matchPattern, RegexOptions.Multiline); string newString = RE.Replace(source, replaceCallback); Console.WriteLine("Replaced String = " + newString); }
To use this callback method with the static
Replace
method, modify the previous
ComplexReplace
method as follows:
public void ComplexReplace(string matchPattern, string source) { MatchEvaluator replaceCallback = new MatchEvaluator(MatchHandler); string newString = Regex.Replace(source, matchPattern, replaceCallback); Console.WriteLine("Replaced String = " + newString); }
where source
is the original string to run
the replace operation against, and
matchPattern
is the regular expression
pattern to match in the source
string.
If the ComplexReplace
method is called from the
following code:
public static void TestComplexReplace( ) { string matchPattern = "<.*>"; string source = @"<?xml version=""1.0"" encoding=""UTF-8""?> <Window ID=""Main""> <Control ID=""TextBox""> <Property Top=""-100"" Left=""0"" Text=""BLANK""/> </Control> <Control ID=""Label""> <Property Top=""99990"" Left=""0"" Caption=""Enter Name Here""/> </Control> </Window>"; ComplexReplace(matchPattern, source); }
only the Top
attributes of the
Property
tags are changed from their original
values to 0
.
The result of this replace action will change only the
Top
property value of a
Property
tag to zero if it is less than zero or
greater than 5000
. Any other tag that contains a
Top
property will remain unchanged. The following
two lines of the source
string will be changed
from:
<Property Top="100" Left="0" Text="BLANK"/> <Property Top="99999" Left="0" Caption="Enter Name Here"/>
to:
<Property Top="100" Left="0" Text="BLANK"/> <Property Top="0" Left="0" Caption="Enter Name Here"/>
The MatchEvaluator
delegate, which is
automatically invoked when it is supplied as a parameter to the
Regexp
class’s
Replace
method, allows for custom replacement of
each string that conforms to the regular expression pattern.
If the current Match
object is operating on a
Property
tag whose Top
property
is out of the specified range, the code within the
MatchHandler
callback method returns a new
modified string. Otherwise, the currently matched string is returned
unchanged. This ability allows you to override the default
Replace
functionality by replacing only that part
of the source
string that meets certain criteria.
The code within this callback method gives you some idea of what can
be accomplished using this replacement technique.
To make use of this callback method, we need a way to call it from
the ComplexReplace
method. First, a variable of
type System.Text.RegularExpressions.MatchEvaluator
is created. This variable (replaceCallback
) is the
delegate that is used to call the MatchHandler
method:
MatchEvaluator replaceCallback = new MatchEvaluator(MatchHandler);
Finally, the Replace
method is called with the
reference to the MatchEvaluator
delegate passed in
as a parameter:
string newString = RE.Replace(source, replaceCallback);