@@ -57,9 +57,31 @@ namespace Org.XmlUnit.Placeholder {
5757 public class PlaceholderDifferenceEvaluator {
5858 public static readonly string PLACEHOLDER_DEFAULT_OPENING_DELIMITER_REGEX = Regex . Escape ( "${" ) ;
5959 public static readonly string PLACEHOLDER_DEFAULT_CLOSING_DELIMITER_REGEX = Regex . Escape ( "}" ) ;
60+ /// <remarks>
61+ /// <para>
62+ /// since 2.8.0
63+ /// </para>
64+ /// </remarks>
65+ public static readonly string PLACEHOLDER_DEFAULT_ARGS_OPENING_DELIMITER_REGEX = Regex . Escape ( "(" ) ;
66+
67+ /// <remarks>
68+ /// <para>
69+ /// since 2.8.0
70+ /// </para>
71+ /// </remarks>
72+ public static readonly string PLACEHOLDER_DEFAULT_ARGS_CLOSING_DELIMITER_REGEX = Regex . Escape ( ")" ) ;
73+
74+ /// <remarks>
75+ /// <para>
76+ /// since 2.8.0
77+ /// </para>
78+ /// </remarks>
79+ public static readonly string PLACEHOLDER_DEFAULT_ARGS_SEPARATOR_REGEX = Regex . Escape ( "," ) ;
80+
6081 private static readonly string PLACEHOLDER_PREFIX_REGEX = Regex . Escape ( "xmlunit." ) ;
6182 // IReadOnlyDictionary is .NET Framework 4.5
6283 private static readonly IDictionary < string , IPlaceholderHandler > KNOWN_HANDLERS ;
84+ private static readonly string [ ] NO_ARGS = new string [ 0 ] ;
6385
6486 static PlaceholderDifferenceEvaluator ( ) {
6587 var m = new Dictionary < string , IPlaceholderHandler > ( ) ;
@@ -88,6 +110,8 @@ private static IEnumerable<Type> GetLoadableTypes(Assembly assembly) {
88110 }
89111
90112 private readonly Regex placeholderRegex ;
113+ private readonly Regex argsRegex ;
114+ private readonly Regex argsSplitter ;
91115
92116 /// <summary>
93117 /// Creates a PlaceholderDifferenceEvaluator with default
@@ -113,7 +137,50 @@ public PlaceholderDifferenceEvaluator() : this(null, null) {
113137 /// PlaceholderDifferenceEvaluator#PLACEHOLDER_DEFAULT_CLOSING_DELIMITER_REGEX
114138 /// if the parameter is null or blank</param>
115139 public PlaceholderDifferenceEvaluator ( string placeholderOpeningDelimiterRegex ,
116- string placeholderClosingDelimiterRegex ) {
140+ string placeholderClosingDelimiterRegex )
141+ : this ( placeholderOpeningDelimiterRegex , placeholderClosingDelimiterRegex , null , null , null ) {
142+ }
143+
144+ /// <summary>
145+ /// Creates a PlaceholderDifferenceEvaluator with default
146+ /// delimiters PLACEHOLDER_DEFAULT_OPENING_DELIMITER_REGEX and
147+ /// PLACEHOLDER_DEFAULT_CLOSING_DELIMITER_REGEX.
148+ /// </summary>
149+ /// <param name="placeholderOpeningDelimiterRegex">regular
150+ /// expression for the opening delimiter of placeholder,
151+ /// defaults to
152+ /// PlaceholderDifferenceEvaluator#PLACEHOLDER_DEFAULT_OPENING_DELIMITER_REGEX
153+ /// if the parameter is null or blank</param>
154+ /// <param name="placeholderClosingDelimiterRegex">regular
155+ /// expression for the closing delimiter of placeholder,
156+ /// defaults to
157+ /// PlaceholderDifferenceEvaluator#PLACEHOLDER_DEFAULT_CLOSING_DELIMITER_REGEX
158+ /// if the parameter is null or blank</param>
159+ /// <param name="placeholderArgsOpeningDelimiterRegex">regular
160+ /// expression for the opening delimiter of the placeholder's
161+ /// argument list, defaults to
162+ /// PlaceholderDifferenceEvaluator#PLACEHOLDER_DEFAULT_ARGS_OPENING_DELIMITER_REGEX
163+ /// if the parameter is null or blank</param>
164+ /// <param name="placeholderArgsClosingDelimiterRegex">regular
165+ /// expression for the closing delimiter of the placeholder's
166+ /// argument list, defaults to
167+ /// PlaceholderDifferenceEvaluator#PLACEHOLDER_DEFAULT_ARGS_CLOSING_DELIMITER_REGEX
168+ /// if the parameter is null or blank</param>
169+ /// <param name="placeholderArgsSeparatorRegex">regular
170+ /// expression for the delimiter between arguments inside of
171+ /// the placeholder's argument list, defaults to
172+ /// PlaceholderDifferenceEvaluator#PLACEHOLDER_DEFAULT_ARGS_SEPARATOR_REGEX
173+ /// if the parameter is null or blank</param>
174+ /// <remarks>
175+ /// <para>
176+ /// since 2.8.0
177+ /// </para>
178+ /// </remarks>
179+ public PlaceholderDifferenceEvaluator ( string placeholderOpeningDelimiterRegex ,
180+ string placeholderClosingDelimiterRegex ,
181+ string placeholderArgsOpeningDelimiterRegex ,
182+ string placeholderArgsClosingDelimiterRegex ,
183+ string placeholderArgsSeparatorRegex ) {
117184 if ( placeholderOpeningDelimiterRegex == null
118185 || placeholderOpeningDelimiterRegex . Trim ( ) . Length == 0 ) {
119186 placeholderOpeningDelimiterRegex = PLACEHOLDER_DEFAULT_OPENING_DELIMITER_REGEX ;
@@ -122,10 +189,26 @@ public PlaceholderDifferenceEvaluator(string placeholderOpeningDelimiterRegex,
122189 || placeholderClosingDelimiterRegex . Trim ( ) . Length == 0 ) {
123190 placeholderClosingDelimiterRegex = PLACEHOLDER_DEFAULT_CLOSING_DELIMITER_REGEX ;
124191 }
192+ if ( placeholderArgsOpeningDelimiterRegex == null
193+ || placeholderArgsOpeningDelimiterRegex . Trim ( ) . Length == 0 ) {
194+ placeholderArgsOpeningDelimiterRegex = PLACEHOLDER_DEFAULT_ARGS_OPENING_DELIMITER_REGEX ;
195+ }
196+ if ( placeholderArgsClosingDelimiterRegex == null
197+ || placeholderArgsClosingDelimiterRegex . Trim ( ) . Length == 0 ) {
198+ placeholderArgsClosingDelimiterRegex = PLACEHOLDER_DEFAULT_ARGS_CLOSING_DELIMITER_REGEX ;
199+ }
200+ if ( placeholderArgsSeparatorRegex == null
201+ || placeholderArgsSeparatorRegex . Trim ( ) . Length == 0 ) {
202+ placeholderArgsSeparatorRegex = PLACEHOLDER_DEFAULT_ARGS_SEPARATOR_REGEX ;
203+ }
125204
126205 placeholderRegex = new Regex ( "(\\ s*" + placeholderOpeningDelimiterRegex
127206 + "\\ s*" + PLACEHOLDER_PREFIX_REGEX + "(.+)" + "\\ s*"
128207 + placeholderClosingDelimiterRegex + "\\ s*)" ) ;
208+ argsRegex = new Regex ( "((.*)\\ s*" + placeholderArgsOpeningDelimiterRegex
209+ + "(.+)"
210+ + "\\ s*" + placeholderArgsClosingDelimiterRegex + "\\ s*)" ) ;
211+ argsSplitter = new Regex ( placeholderArgsSeparatorRegex ) ;
129212 }
130213
131214 /// <summary>
@@ -171,7 +254,7 @@ public ComparisonResult Evaluate(Comparison comparison, ComparisonResult outcome
171254 private bool IsMissingTextNodeDifference ( Comparison comparison ) {
172255 return ControlHasOneTextChildAndTestHasNone ( comparison )
173256 || CantFindControlTextChildInTest ( comparison ) ;
174- }
257+ }
175258
176259 private bool ControlHasOneTextChildAndTestHasNone ( Comparison comparison ) {
177260 Comparison . Detail controlDetails = comparison . ControlDetails ;
@@ -254,14 +337,24 @@ private ComparisonResult EvaluateAttributeListLengthConsideringPlaceholders(Comp
254337
255338 private ComparisonResult EvaluateConsideringPlaceholders ( string controlText , string testText ,
256339 ComparisonResult outcome ) {
257- Match m = placeholderRegex . Match ( controlText ) ;
258- if ( m . Success ) {
259- string keyword = m . Groups [ 2 ] . Captures [ 0 ] . Value . Trim ( ) ;
340+ Match placeholderMatch = placeholderRegex . Match ( controlText ) ;
341+ if ( placeholderMatch . Success ) {
342+ string content = placeholderMatch . Groups [ 2 ] . Captures [ 0 ] . Value . Trim ( ) ;
343+ Match argsMatch = argsRegex . Match ( content ) ;
344+ string keyword ;
345+ string [ ] args ;
346+ if ( argsMatch . Success ) {
347+ keyword = argsMatch . Groups [ 2 ] . Captures [ 0 ] . Value . Trim ( ) ;
348+ args = argsSplitter . Split ( argsMatch . Groups [ 3 ] . Captures [ 0 ] . Value ) ;
349+ } else {
350+ keyword = content ;
351+ args = NO_ARGS ;
352+ }
260353 if ( IsKnown ( keyword ) ) {
261- if ( m . Groups [ 1 ] . Captures [ 0 ] . Value . Trim ( ) != controlText . Trim ( ) ) {
354+ if ( placeholderMatch . Groups [ 1 ] . Captures [ 0 ] . Value . Trim ( ) != controlText . Trim ( ) ) {
262355 throw new XMLUnitException ( "The placeholder must exclusively occupy the text node." ) ;
263356 }
264- return Evaluate ( keyword , testText ) ;
357+ return Evaluate ( keyword , testText , args ) ;
265358 }
266359 }
267360
@@ -273,8 +366,8 @@ private bool IsKnown(string keyword) {
273366 return KNOWN_HANDLERS . ContainsKey ( keyword ) ;
274367 }
275368
276- private ComparisonResult Evaluate ( string keyword , string testText ) {
277- return KNOWN_HANDLERS [ keyword ] . Evaluate ( testText ) ;
369+ private ComparisonResult Evaluate ( string keyword , string testText , string [ ] args ) {
370+ return KNOWN_HANDLERS [ keyword ] . Evaluate ( testText , args ) ;
278371 }
279372 }
280373}
0 commit comments