@@ -332,53 +332,71 @@ private static int DetectIndentation(string xmlPath)
332332 private static void ApplyAdd ( XElement addElement , XElement originalRoot )
333333 {
334334 string sel = addElement . Attribute ( "sel" ) ? . Value ?? throw new ArgumentException ( "The 'sel' attribute is required." ) ;
335- string pos = addElement . Attribute ( "pos" ) ? . Value ?? "append" ;
336-
337- Logger . Debug ( $ "Applying add operation: { sel } at { pos } ") ;
335+ string ? type = addElement . Attribute ( "type" ) ? . Value ;
336+ string ? pos = addElement . Attribute ( "pos" ) ? . Value ;
337+ if ( pos == null && type == null ) {
338+ pos = "append" ;
339+ }
338340
339- var newElements = addElement . Elements ( ) ;
341+ Logger . Debug ( $ "Applying add operation: { sel } at { pos ! } " ) ;
340342
341- var targetNodes = originalRoot . XPathEvaluate ( sel ) as IEnumerable < object > ;
342- if ( targetNodes == null || ! targetNodes . Any ( ) )
343+ var targetElements = originalRoot . XPathSelectElements ( sel ) ;
344+ if ( targetElements == null || ! targetElements . Any ( ) )
343345 {
344346 Logger . Warn ( $ "No nodes found for add selector: { sel } ") ;
345347 return ;
346348 }
347-
348- foreach ( var targetObj in targetNodes )
349+ if ( targetElements . Count ( ) > 1 )
349350 {
350- if ( targetObj is XElement target )
351+ Logger . Warn ( $ "Multiple nodes found for add selector: { sel } . Skipping.") ;
352+ return ;
353+ }
354+ var targetElement = targetElements . First ( ) ;
355+ if ( pos != null ) {
356+ var newElements = addElement . Elements ( ) ;
357+ foreach ( var newElem in newElements )
351358 {
352- foreach ( var newElem in newElements )
359+ XElement cloned = new XElement ( newElem ) ;
360+ if ( pos == "before" )
353361 {
354- XElement cloned = new XElement ( newElem ) ;
355- if ( pos == "before" )
356- {
357- target . AddBeforeSelf ( cloned ) ;
358- Logger . Info ( $ "Added new element '{ cloned . Name } ' before '{ target . Name } ' in '{ target . Parent ? . Name } '.") ;
359- }
360- else if ( pos == "after" )
361- {
362- target . AddAfterSelf ( cloned ) ;
363- Logger . Info ( $ "Added new element '{ cloned . Name } ' after '{ target . Name } ' in '{ target . Parent ? . Name } '.") ;
364- }
365- else if ( pos == "prepend" )
366- {
367- target . AddFirst ( cloned ) ;
368- Logger . Info ( $ "Prepended new element '{ cloned . Name } ' to '{ target . Name } '.") ;
369- }
370- else if ( pos == "append" )
371- {
372- target . Add ( cloned ) ;
373- Logger . Info ( $ "Appended new element '{ cloned . Name } ' to '{ target . Name } '.") ;
374- }
375- else
376- {
377- Logger . Warn ( $ "Unknown position: { pos } . Skipping insertion.") ;
378- }
362+ targetElement . AddBeforeSelf ( cloned ) ;
363+ Logger . Info ( $ "Added new element '{ cloned . Name } ' before '{ targetElement . Name } ' in '{ targetElement . Parent ? . Name } '.") ;
364+ }
365+ else if ( pos == "after" )
366+ {
367+ targetElement . AddAfterSelf ( cloned ) ;
368+ Logger . Info ( $ "Added new element '{ cloned . Name } ' after '{ targetElement . Name } ' in '{ targetElement . Parent ? . Name } '.") ;
369+ }
370+ else if ( pos == "prepend" )
371+ {
372+ targetElement . AddFirst ( cloned ) ;
373+ Logger . Info ( $ "Prepended new element '{ cloned . Name } ' to '{ targetElement . Name } '.") ;
374+ }
375+ else if ( pos == "append" )
376+ {
377+ targetElement . Add ( cloned ) ;
378+ Logger . Info ( $ "Appended new element '{ cloned . Name } ' to '{ targetElement . Name } '.") ;
379+ }
380+ else
381+ {
382+ Logger . Warn ( $ "Unknown position: { pos } . Skipping insertion.") ;
379383 }
380384 }
381385 }
386+ else if ( type != null )
387+ {
388+ if ( type . StartsWith ( '@' ) && type . Length > 1 ) {
389+ type = type . Substring ( 1 ) ;
390+ if ( addElement . Value == null )
391+ {
392+ Logger . Warn ( "Attribute add operation missing value." ) ;
393+ return ;
394+ }
395+ targetElement . SetAttributeValue ( type , addElement . Value ) ;
396+ Logger . Info ( $ "Added attribute '{ type } ' with value '{ addElement . Value } ' to '{ targetElement . Name } '.") ;
397+ }
398+ }
399+
382400 }
383401
384402 private static void ApplyReplace ( XElement replaceElement , XElement originalRoot )
0 commit comments