Tuesday, August 22, 2023

PowerShell to write XML with attributes on new line

Context

Many times after patch deployment of the application into the server there will be questions on what changed? The source code is obviously changed and the binaries can't be compared to find out what changed.

But the textual configuration files can easily be compared. Take a backup of existing files. Do the patching and compare what changed.

This post is assuming the deployment tools are using PowerShell to change the config files.

Problem

Look at the image below.

It shows there are a lot of changes done to the file. But really there is only one change. dbserver3->dbserver2

As we can easily understand the comparison considered the files as text, not as XML, and found a lot of differences.

Approaches

If the number of files is less this is fine but that is not the case in enterprise. There are multiple approaches to this problem.

A tool that understands XML and compares

The above comparison tool is not recognizing the XML format instead it compared textually. Find another tool that understands the XML format and compare accordingly.

To date, we didn't find any such tool. Please comment if there are tools that are free and export the comparison report.

Always have attributes on a new line

In this approach make sure all the tools and programs that modify the XML write attributes on a new line.
Since PowerShell is running on top of .Net it is easy to get anything working in PowerShell that works in .Net. Google easily lands us in pages that say use the XMLWriterSettings.NewLineOnAttributes to get the job done. Unfortunately, it is not working out of the box.

But when we combine the .Indent property with .NewLineOnAttributes, it works fine.

[XML]$doc = get-content ".\input.xml"
$xwSettings = new-object System.Xml.XmlWriterSettings
$xwSettings.Indent = $true
$xwSettings.NewLineOnAttributes = $true
$xmlWriter = [Xml.XmlWriter]::Create("output.xml", $xwSettings)
$doc.Save($xmlWriter)
$xmlWriter.Dispose()

The above code works. Now the question is, is this documented? Oh yes in the remarks section.
Of course, the default value of the Indent property is false. The comparison looks as below after using the above code.


Happy formatting.

No comments: