Recently, I received a request to update multiple software xml files to a newer version for QDAS software.
This request can be done by updating our config XMLs file to our required version. The things here is we need to scan for multiple XML files and look into those to find suitable string (for the nodes name) and replace the value of that node name. This can be done manually for around 200 XML files with 5 records need to be looked in every file (
***A quick count
- Around 1,000 records need to be checked and updated manually
- Take up to 10s for look at 1 record and update to the new value.
- Total 10,000/3600s ~ 2 hours 40 mins continuous working.
Ahhh… this makes no sense for every quarterly update spends time like this …. but the more thing is I am not keen on looking up for each value and do the Ctrl + C and Ctrl +V for all these stuff.
I wrote this below PowerShell to achieve what what I should have lost.
Prerequisite
- Please backup all your XML file before making the change
Achievement:
- The Script will make change all the XML files which has the version lower than the one we would like to change, off course, it leave the upper version alone.
- Generate a log file to track what “Changed”, “NOchange” or “ERROR” to review later.
- A final summary to give the total Files has been changed/Which files having error while changing.
Function Update-XMLFile ([string]$XMLPath, [string]$XMLNode, [string]$XMLNodeValue,[string]$logpath)
{
$successcount = 0
$errorcount = 0
$nochangecount = 0
$errorplant = @()
$XMLNodeValuetoInt = [int]$XMLNodeValue.Replace('_','')
$XMLNodeValuefind = $XMLNodeValue.substring(0,5) + '*'
$xmls = Get-ChildItem -path $XMLPath P*.xml -Recurse | ? {$_.basename.length -eq 5}
foreach ($xml in $xmls){
write-host "Checking XML File $($xml.basename)" -ForegroundColor Green
"[INFO]Checking XML File $($xml.basename)"| out-file $logpath\activity.log -Append
[xml]$xmlcontent = Get-Content $xml.fullname
$nodes = $xmlcontent.getElementsByTagName($XMLNode)
If ($null -eq $nodes)
{
write-host "Unable to find specific $XMLNode for XMLFile $($xml.basename)" -ForegroundColor Red
Echo "[ERROR]Unable to find specific $XMLNode for XMLFile $($xml.basename)" | out-file $logpath\activity.log -Append
}
Else
{
Foreach($node in $nodes){
write-host "Checking $($node.ParentNode.name)"
"Checking $($node.ParentNode.name)"| out-file $logpath\activity.log -Append
try {
if(($node.innertext -like $XMLNodeValuefind) -and ([int]$node.innertext.Replace('_','') -ge $XMLNodeValuetoInt)){
$OldXmlNodeValue = $node.innertext
write-host "[NOChange]$($xml.basename) module $($node.ParentNode.name) Version is already at $OldXmlNodeValue" -ForegroundColor Gray
"[NOChange]$($xml.basename) module $($node.ParentNode.name) Version is already at $OldXmlNodeValue" | out-file $logpath\activity.log -Append
$nochangecount ++
}
elseif(($node.innertext -like $XMLNodeValuefind) -and ([int]$node.innertext.Replace('_','') -lt $XMLNodeValuetoInt)){
$OldXmlNodeValue = $node.innertext
$node.innertext = $XMLNodeValue
$xmlcontent.Save($xml.fullname)
write-host "[Changed]$($xml.basename) module $($node.ParentNode.name) Updated: $OldXmlNodeValue --> $XMLNodeValue" -ForegroundColor Blue
"[Changed]$($xml.basename) module $($node.ParentNode.name) Updated : $OldXmlNodeValue --> $XMLNodeValue" | out-file $logpath\activity.log -Append
$successcount ++
}
else{
write-host "[NOChange]$($xml.basename) module $($node.ParentNode.name) Version is not specified" -ForegroundColor Gray
"[NOChange]$($xml.basename) module $($node.ParentNode.name) Version is not specified" | out-file $logpath\activity.log -Append
$nochangecount ++
}
}
catch{
write-host "$($xml.basename) module $($node.ParentNode.name) can not change version`n $($_.Exception.Message)" -ForegroundColor Red
"[ERROR]$($xml.basename) module $($node.ParentNode.name) can not change version `n $($_.Exception.Message)" | out-file $logpath\activity.log -Append
$Errorcount ++
$errorXMLFile += $xml.basename
}
}
}
}
write-host "Total Files proceed : $($xmls.count)"
write-host "Total Files proceed Error: $Errorcount / $errorXMLFile"
write-host "Total Files Modules proceed success: $successcount/$($successcount + $Errorcount)"
"Total Files proceed : $($xmls.count)"| out-file $logpath\activity.log -Append
"Total Files proceed Error: $Errorcount / $errorXMLFile"| out-file $logpath\activity.log -Append
"Total Files Modules proceed success: $successcount/$($successcount + $Errorcount)"| out-file $logpath\activity.log -Append
}
Eg. To call as this
update-xmlfile -XMLPath <FolderPath XMLs Location> -XMLNode "<NodeName>" -XMLNodeValue "<ValueWantUpdateTo>" -logpath "<FolderPath of log file-filename autogenerate>"