@@ -11,6 +11,7 @@ namespace PackageReferenceVersionToAttribute
1111 using System . Threading . Tasks ;
1212 using System . Xml ;
1313 using System . Xml . Linq ;
14+ using System . Xml . XPath ;
1415 using Microsoft . Extensions . Logging ;
1516 using Microsoft . Extensions . Options ;
1617
@@ -54,103 +55,131 @@ public async Task ConvertAsync(IEnumerable<string> projectFilePaths)
5455 {
5556 try
5657 {
57- if ( string . IsNullOrEmpty ( projectFilePath ) || ! File . Exists ( projectFilePath ) )
58- {
59- continue ;
60- }
58+ await this . ConvertAsync ( projectFilePath ) ;
59+ }
60+ catch ( Exception ex )
61+ {
62+ this . logger . LogError ( ex , $ "Error processing project file \" { projectFilePath } \" ") ;
63+ }
64+ }
65+ }
6166
62- string message = $ "Converting PackageReference Version child elements to attributes in the project file \" { projectFilePath } \" ...";
63- this . logger . LogInformation ( message ) ;
67+ private async Task ConvertAsync ( string projectFilePath )
68+ {
69+ if ( string . IsNullOrEmpty ( projectFilePath ) || ! File . Exists ( projectFilePath ) )
70+ {
71+ return ;
72+ }
6473
65- var document = XDocument . Load ( projectFilePath , LoadOptions . PreserveWhitespace ) ;
74+ string message = $ "Converting PackageReference Version child elements to attributes in the project file \" { projectFilePath } \" ...";
75+ this . logger . LogInformation ( message ) ;
6676
67- // Find all PackageReference elements with a <Version> child element
68- // Use the XML namespace if one is set
69- XNamespace ns = document . Root . GetDefaultNamespace ( ) ;
77+ var document = XDocument . Load ( projectFilePath , LoadOptions . PreserveWhitespace ) ;
7078
71- if ( ! string . IsNullOrWhiteSpace ( ns . NamespaceName ) )
72- {
73- this . logger . LogInformation ( $ "Found XML namespace \" { ns . NamespaceName } \" .") ;
74- }
79+ // Find all PackageReference elements with a <Version> child element
80+ // Use the XML namespace if one is set
81+ XNamespace ns = document . Root . GetDefaultNamespace ( ) ;
7582
76- // Query for PackageReference elements
77- var packageReferences = document . Descendants ( ns != null ? ns + "PackageReference" : "PackageReference" )
78- . Where ( pr => pr . Element ( ns != null ? ns + "Version" : "Version" ) != null )
79- . ToList ( ) ;
80- if ( ! packageReferences . Any ( ) )
81- {
82- this . logger . LogInformation ( $ "No PackageReference Version child elements found in the project file \" { projectFilePath } \" .") ;
83- continue ;
84- }
83+ if ( ! string . IsNullOrWhiteSpace ( ns . NamespaceName ) )
84+ {
85+ this . logger . LogInformation ( $ "Found XML namespace \" { ns . NamespaceName } \" .") ;
86+ }
8587
86- bool modified = false ;
88+ // Query for PackageReference elements
89+ var packageReferenceVersionElements = document . Descendants ( ns != null ? ns + "PackageReference" : "PackageReference" )
90+ . Where ( pr => pr . Element ( ns != null ? ns + "Version" : "Version" ) != null )
91+ . ToList ( ) ;
92+ if ( ! packageReferenceVersionElements . Any ( ) )
93+ {
94+ this . logger . LogInformation ( $ "No PackageReference Version child elements found in the project file \" { projectFilePath } \" .") ;
95+ return ;
96+ }
8797
88- if ( this . options . Backup )
89- {
90- // backup project file
91- this . fileService . BackupFile ( projectFilePath ) ;
92- }
98+ bool modified = false ;
9399
94- // check out file from source control
95- await this . sourceControlService . CheckOutFileAsync ( projectFilePath ) ;
100+ foreach ( var packageReferenceVersionElement in packageReferenceVersionElements )
101+ {
102+ var versionElement = packageReferenceVersionElement . Element ( ns != null ? ns + "Version" : "Version" ) ;
103+ if ( versionElement != null )
104+ {
105+ // Move the Version element content to an attribute
106+ packageReferenceVersionElement . SetAttributeValue ( "Version" , versionElement . Value ) ;
107+ versionElement . Remove ( ) ;
96108
97- if ( this . options . Force )
109+ // Check if the PackageReference is empty and set it to self-closing if so
110+ if ( ! packageReferenceVersionElement . HasElements )
98111 {
99- this . fileService . RemoveReadOnlyAttribute ( projectFilePath ) ;
112+ // This will make sure it's treated as a self-closing tag when saved
113+ // Optionally, trim empty lines around the parent element
114+ packageReferenceVersionElement . RemoveNodes ( ) ; // Remove empty nodes
100115 }
101116
102- foreach ( var packageReference in packageReferences )
103- {
104- var versionElement = packageReference . Element ( ns != null ? ns + "Version" : "Version" ) ;
105- if ( versionElement != null )
106- {
107- // Move the Version element content to an attribute
108- packageReference . SetAttributeValue ( "Version" , versionElement . Value ) ;
109- versionElement . Remove ( ) ;
110-
111- // Check if the PackageReference is empty and set it to self-closing if so
112- if ( ! packageReference . HasElements )
113- {
114- // This will make sure it's treated as a self-closing tag when saved
115- // Optionally, trim empty lines around the parent element
116- packageReference . RemoveNodes ( ) ; // Remove empty nodes
117- }
118-
119- modified = true ;
120- }
121- }
117+ modified = true ;
118+ }
119+ }
120+
121+ // Save changes only if any modifications were made
122+ if ( ! modified )
123+ {
124+ return ;
125+ }
126+
127+ if ( this . options . Backup )
128+ {
129+ // backup project file
130+ this . fileService . BackupFile ( projectFilePath ) ;
131+ }
132+
133+ // check out file from source control
134+ await this . sourceControlService . CheckOutFileAsync ( projectFilePath ) ;
135+
136+ if ( this . options . Force )
137+ {
138+ this . fileService . RemoveReadOnlyAttribute ( projectFilePath ) ;
139+ }
140+
141+ // remove empty lines within <PackageReference> elements
142+ // Select all <PackageReference> elements
143+ var packageReferenceElements = document . XPathSelectElements ( "//PackageReference" ) ;
144+
145+ foreach ( var packageReferenceElement in packageReferenceElements )
146+ {
147+ // Get all the child nodes of the <PackageReference>
148+ var childNodes = packageReferenceElement . Nodes ( ) ;
122149
123- // Save changes if any modifications were made
124- if ( modified )
150+ // Iterate through the child nodes
151+ foreach ( var node in childNodes )
152+ {
153+ // Check if the node is a text node and contains only whitespace
154+ if ( node is XText textNode && string . IsNullOrWhiteSpace ( textNode . Value ) )
125155 {
126- var settings = new XmlWriterSettings
127- {
128- OmitXmlDeclaration = document . Declaration == null , // Preserve the XML declaration if it exists.
129- Indent = false , // Prevents adding any extra indentation
130- NewLineHandling = NewLineHandling . Replace ,
131- } ;
132-
133- if ( this . options . DryRun )
134- {
135- // Output the modified document to the console for review
136- using var stringWriter = new StringWriter ( ) ;
137- using var xmlWriter = XmlWriter . Create ( stringWriter , settings ) ;
138-
139- document . WriteTo ( xmlWriter ) ;
140- xmlWriter . Flush ( ) ;
141- this . logger . LogInformation ( stringWriter . ToString ( ) ) ;
142- }
143- else
144- {
145- using var writer = XmlWriter . Create ( projectFilePath , settings ) ;
146- document . Save ( writer ) ; // Preserves original formatting, avoids extra lines
147- }
156+ // Remove the empty line
157+ textNode . Remove ( ) ;
148158 }
149159 }
150- catch ( Exception ex )
151- {
152- this . logger . LogError ( ex , $ "Error processing project file \" { projectFilePath } \" ") ;
153- }
160+ }
161+
162+ var settings = new XmlWriterSettings
163+ {
164+ OmitXmlDeclaration = document . Declaration == null , // Preserve the XML declaration if it exists.
165+ Indent = false , // Prevents adding any extra indentation
166+ NewLineHandling = NewLineHandling . Replace ,
167+ } ;
168+
169+ if ( this . options . DryRun )
170+ {
171+ // Output the modified document to the console for review
172+ using var stringWriter = new StringWriter ( ) ;
173+ using var xmlWriter = XmlWriter . Create ( stringWriter , settings ) ;
174+
175+ document . WriteTo ( xmlWriter ) ;
176+ xmlWriter . Flush ( ) ;
177+ this . logger . LogInformation ( stringWriter . ToString ( ) ) ;
178+ }
179+ else
180+ {
181+ using var writer = XmlWriter . Create ( projectFilePath , settings ) ;
182+ document . Save ( writer ) ; // Preserves original formatting, avoids extra lines
154183 }
155184 }
156185 }
0 commit comments