I want to remove comments in xml files based on the xml tags inside the comment with Powershell.
Constraints:
- Multi line comments should be supported
- Keep xml formatting (e.g. do not write everything into a single line or remove indents)
- Keep file encoding
My function UncommentXmlNode should remove the <!-- ... --> and keep the <InnerXml>.
My function UncommentMyTwoNodes should remove comments from two different xml tags.
You find two tests:
it "uncomments myFirstOutcommentedXml and mySecondOutcommentedXml"is running smoothlyit "uncomments both if both are in same comment"fails unless you insert (`n)?.*. In that case, 1. breaks.
The tests are fairly easy to understand, if you look at [xml]$expected and the two respective [xml]$inputXml values. The code here is a fully functional Pester test suite to reproduce my issue. You might have to create C:\temp or install Pester v5.
Import-Module Pester
Describe "Remove comments"{
BeforeAll {
function UncommentXmlNode {
param (
[String] $filePath,
[String] $innerXmlToUncomment
)
$content = Get-Content $filePath -Raw
$content -replace "<!--(?<InnerXml>$innerXmlToUncomment)-->", '${InnerXml}' | Set-Content -Path $filePath -Encoding utf8
}
function UncommentMyTwoNodes {
param (
[xml]$inputXml,
[string]$inputXmlPath
)
UncommentXmlNode -filePath $inputXmlPath -innerXmlToUncomment "<myFirstOutcommentedXml.*" #Add this to make second test work (`n)?.*
UncommentXmlNode -filePath $inputXmlPath -innerXmlToUncomment "<mySecondOutcommentedXml.*"
}
[xml]$expected = @"
<myXml>
<!-- comment I want to keep -->
<myFirstOutcommentedXml attributeA="xy" attributeB="true" />
<mySecondOutcommentedXml attributeA="xy" attributeB="true" />
<myOtherXmlTag attributeC="value" />
<!-- comment I want to keep -->
</myXml>
"@
}
it "uncomments myFirstOutcommentedXml and mySecondOutcommentedXml"{
[xml]$inputXml = @"
<myXml>
<!-- comment I want to keep -->
<!--<myFirstOutcommentedXml attributeA="xy" attributeB="true" />-->
<!--<mySecondOutcommentedXml attributeA="xy" attributeB="true" />-->
<myOtherXmlTag attributeC="value" />
<!-- comment I want to keep -->
</myXml>
"@
$tempPath = "C:\temp\test.xml"
$inputXml.Save($tempPath)
UncommentMyTwoNodes -inputXml $inputXml -inputXmlPath $tempPath
[xml]$result = Get-Content $tempPath
$result.OuterXml | Should -be $expected.OuterXml
}
it "uncomments both if both are in same comment"{
[xml]$inputXml = @"
<myXml>
<!-- comment I want to keep -->
<!--<myFirstOutcommentedXml attributeA="xy" attributeB="true" />
<mySecondOutcommentedXml attributeA="xy" attributeB="true" />-->
<myOtherXmlTag attributeC="value" />
<!-- comment I want to keep -->
</myXml>
"@
$tempPath = "C:\temp\test.xml"
$inputXml.Save($tempPath)
UncommentMyTwoNodes -inputXml $inputXml -inputXmlPath $tempPath
[xml]$result = Get-Content $tempPath
$result.OuterXml | Should -be $expected.OuterXml
}
}