Surgical XML editing with Powershell
Asked Answered
W

1

8

I'm working with csproj files using Powershell to perform large-scale editing of project references. So far I've managed to edit the Include attributes on ProjectReferences using the following lines:

    $projectXml = [xml](Get-Content $_.Project.FullName)
    Add-TfsPendingChange -edit $_.Project.FullName -ErrorAction Stop
    $projectXml | Select-Xml -namespace @{msb = "http://schemas.microsoft.com/developer/msbuild/2003"} -xpath "//msb:ProjectReference[msb:Project='$projectGuid']" | Select-Object -ExpandProperty Node | foreach { $_.Include = "$newPath" }
    $projectXml.Save($_.Project.FullName)

This works, and replaces the Include attribute on the appropriate ProjectReferences as I expect. However, there are plenty of additional "harmless" changes made, such as formatting all tags on their own line, e.g.
<FileUpgradeFlags></FileUpgradeFlags>

becomes

<FileUpgradeFlags>
</FileUpgradeFlags>

Is there any way to perform an edit such as this that doesn't have these side effects?

edit: for clarity to anyone who finds this post for other reasons, Select-MsBuildXml is just a wrapper function I wrote around Select-Xml that pre-loads the namespace parameter with the msbuild namespace, and expands the node property afterwards.

Walli answered 28/2, 2011 at 19:39 Comment(4)
I'm curious to know why the extra whitespace poses a problem for you.Aggressive
Mainly because it creates additional work in reviewing the changes, and also because it creates needless churn in source control. In the pathological case, VS would choose to reformat all these line-broken tags into single-line elements, thus stirring everything up again next time a change is made to the csproj document, and the two become locked in an irritating format grapple.Walli
Could this be done (and shown) with Select-XML instead of Select-MsBuildXml to make this answer more applicable to others?Welldefined
It's funny that you mention this since I thought I had already ported it for general consumption; my Select-MsBuildXml cmdlet is so second nature at this point I overlooked it. It just loads the msbuild namespace and expands the node property, nothing special. I converted it to Select-Xml.Walli
M
12

I did a lot of VS project manipulation a few years back. Seems like creating the XmlDocument and using Load directly (versus using Get-Content and casting to XML) worked better for me:

$path = "C:\temp\foo.csproj"
$proj = new-object system.xml.xmldocument
$proj.PreserveWhitespace = $true
$proj.Load($path)
...
$proj.Save($path)

Update - Try setting the PreserveWhitespace property to true before loading the XML document as shown above.

Moyer answered 1/3, 2011 at 0:55 Comment(3)
Thanks for the hint, but unfortunately it seems that the outcome is the same. Hopefully VS will be gentle with the nonstandard formatting.Walli
I updated the answer to include setting the PreserveWhitespace property on the XmlDocument. This seems to help.Moyer
Most excellent! This will save me a lot of review headaches. Thank you very much!Walli

© 2022 - 2024 — McMap. All rights reserved.