Remove Duplicate XML Node Groups in Powershell

Viewed 162

I have a XML File which due to rerunning of scripts and folder structure can contain duplicate package elements (see last two packages in example XML).
Now I need a Powershell function which removes all duplicate packages. A duplicate in this case is defined by a exact combination of manufacturer, name, version, filename and exeversion. Same softwarepackages with different versions for example, shouldn't be deleted.

Example XML:

<?xml version="1.0" encoding="iso-8859-1"?>
<softwaremetering xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="softwaremetering.xsd">
  <package>
    <manufacturer>BAFU</manufacturer>
    <name>EconoMe-Offline</name>
    <version>3.0</version>
    <filename>
    </filename>
    <exeversion>
    </exeversion>
  </package>
  <package>
    <manufacturer>BAFU</manufacturer>
    <name>EconoMe-Offline</name>
    <version>4.0.20</version>
    <filename>EconoMe-4_WinStart.exe</filename>
    <exeversion>*</exeversion>
  </package>
  <package>
    <manufacturer>BAFU</manufacturer>
    <name>Hakesch</name>
    <version>1.0.3b</version>
    <filename>
    </filename>
    <exeversion>
    </exeversion>
  </package>
  <package>
    <manufacturer>BAFU</manufacturer>
    <name>Hakesch</name>
    <version>1.04</version>
    <filename>hakesch.exe</filename>
    <exeversion>*</exeversion>
  </package>
  <package>
    <manufacturer>Balesio</manufacturer>
    <name>ALLCaptureEnterprise</name>
    <version>3.0</version>
    <filename>
    </filename>
    <exeversion>
    </exeversion>
  </package>
  <package>
    <manufacturer>Banana</manufacturer>
    <name>Buchhaltung</name>
    <version>7.0</version>
    <filename>
    </filename>
    <exeversion>
    </exeversion>
  </package>
  <package>
    <manufacturer>Banana</manufacturer>
    <name>Buchhaltung</name>
    <version>9.0</version>
    <filename>banana90.exe</filename>
    <exeversion>*</exeversion>
  </package>
  <package>
    <manufacturer>Banana</manufacturer>
    <name>Buchhaltung</name>
    <version>9.0.4</version>
    <filename>Banana90.exe</filename>
    <exeversion>*</exeversion>
  </package>
  <package>
    <manufacturer>Barco</manufacturer>
    <name>ClickShare-Extension-Pack</name>
    <version>1.0.2.3</version>
    <filename>clicksharelauncher.exe</filename>
    <exeversion>*</exeversion>
  </package>
  <package>
    <manufacturer>Barco</manufacturer>
    <name>ClickShare-Extension-Pack</name>
    <version>1.0.4.3</version>
    <filename>clicksharelauncher.exe</filename>
    <exeversion>*</exeversion>
  </package>
  <package>
    <manufacturer>Bernina</manufacturer>
    <name>Sticksoftware</name>
    <version>5.0</version>
    <filename>
    </filename>
    <exeversion>
    </exeversion>
  </package>
  <package>
    <manufacturer>Bernina</manufacturer>
    <name>Sticksoftware</name>
    <version>5.0</version>
    <filename>
    </filename>
    <exeversion>
    </exeversion>
  </package>
</softwaremetering>
1 Answers

As Wasif Hasan already commented, you can make use of the Group-Object for this.

[xml]$xml = Get-Content -Path 'X:\TheXmlFile.xml' -Raw

# find duplicate package nodes regarding all the properties that can make them a duplicate
$xml.softwaremetering.package | 
    Group-Object manufacturer,name,version,filename,exeversion | 
    Where-Object { $_.Count -gt 1 } | 
    ForEach-Object {
        $nodesToRemove = $_.Group | Select-Object -Skip 1
        foreach ($node in $nodesToRemove) {
            [void]$node.ParentNode.RemoveChild($node)
        }
}

# save to new file
$xml.Save("X:\TheUniqifiedXml.xml")
Related