Home > OS >  Compare two XML files - output unique
Compare two XML files - output unique

Time:01-26

I have two xml files with the same format, I can get the output in powershell to display each file correctly but I need to compare StatusErrorResultsFiltered.xml to StatusErrorResults.xml and output the unique entries that exist in one but not both files,excluding the "description" field.

Current Code:

$XMLPath = "C:\Users\John.Doe\Desktop\Projects\Powershell\backend library conversion\TEST\"

# Exporting the unique results as undefined errors to an XML file
$filteredResults = [xml](Get-Content "$XMLPath/Output/StatusErrorResultsFiltered.xml")
$unitResults = [xml](Get-Content "$XMLPath/StatusErrorResults.xml")

$originalEntries = $unitResults.Objs.obj.ms.s | Where-Object {$_.N -eq "Device" -or $_.N -eq "Mstatus"}
$filteredEntries = $filteredResults.Objs.obj.ms.s | Where-Object {$_.N -eq "Device" -or $_.N -eq "Mstatus"}

# Using Compare-Object to find unique entries
$uniqueEntries = Compare-Object $originalEntries $filteredEntries -Property Device,Mstatus |
Select-Object -Property Device,Mstatus |
Sort-Object -unique -Property Device,Mstatus 

$uniqueEntries | Export-Clixml -Path "$XMLPath\Output\UndefinedErrors.xml"

Currently the undefinedErrors.xml is showing one node with Device and Mstatus but does not actually include the data that should be there.

<Objs xmlns="http://schemas.microsoft.com/powershell/2004/04" Version="1.1.0.1">
<Obj RefId="0">
<TN RefId="0">
<T>Selected.System.Management.Automation.PSCustomObject</T>
<T>System.Management.Automation.PSCustomObject</T>
<T>System.Object</T>
</TN>
<MS>
<Nil N="Device"/>
<Nil N="Mstatus"/>
</MS>
</Obj>
</Objs>

StatusErrorResultsFiltered.xml

<Objs xmlns="http://schemas.microsoft.com/powershell/2004/04" Version="1.1.0.1">
<Obj RefId="0">
<TN RefId="0">
<T>System.Management.Automation.PSCustomObject</T>
<T>System.Object</T>
</TN>
<MS>
<S N="Device">DeviceName5</S>
<S N="Mstatus">5</S>
<S N="Description">Generic Text for example</S>
</MS>
</Obj>
<Obj RefId="1">
<TNRef RefId="0"/>
<MS>
<S N="Device">DeviceName4</S>
<S N="Mstatus">38</S>
<S N="Description">Generic Text for example</S>
</MS>
</Obj>
<Obj RefId="2">
<TNRef RefId="0"/>
<MS>
<S N="Device">DeviceName3</S>
<S N="Mstatus">18</S>
<S N="Description">Generic Text for example</S>
</MS>
</Obj>
<Obj RefId="3">
<TNRef RefId="0"/>
<MS>
<S N="Device">DeviceName2</S>
<S N="Mstatus">16</S>
<S N="Description">Generic Text for example</S>
</MS>
</Obj>
<Obj RefId="4">
<TNRef RefId="0"/>
<MS>
<S N="Device">DeviceName1</S>
<S N="Mstatus">49</S>
<S N="Description">Generic Text for example</S>
</MS>
</Obj>
</Objs>

StatusErrorResults.xml

<Objs xmlns="http://schemas.microsoft.com/powershell/2004/04" Version="1.1.0.1">
    <Obj RefId="0">
    <TN RefId="0">
    <T>System.Management.Automation.PSCustomObject</T>
    <T>System.Object</T>
    </TN>
    <MS>
    <S N="Device">DeviceName5</S>
    <S N="Mstatus">5</S>
    </MS>
    </Obj>
    <Obj RefId="1">
    <TNRef RefId="0"/>
    <MS>
    <S N="Device">DeviceName4</S>
    <S N="Mstatus">38</S>
    </MS>
    </Obj>
    <Obj RefId="2">
    <TNRef RefId="0"/>
    <MS>
    <S N="Device">DeviceName3</S>
    <S N="Mstatus">18</S>
    </MS>
    </Obj>
    <Obj RefId="3">
    <TNRef RefId="0"/>
    <MS>
    <S N="Device">DeviceName2</S>
    <S N="Mstatus">16</S>
    </MS>
    </Obj>
    <Obj RefId="4">
    <TNRef RefId="0"/>
    <MS>
    <S N="Device">DeviceName1</S>
    <S N="Mstatus">49</S>
    </MS>
    </Obj>
<Obj RefId="5">
<TNRef RefId="0"/>
<MS>
<S N="Device">DeviceName6</S>
<S N="Mstatus">16</S>
</MS>
</Obj>
<Obj RefId="6">
<TNRef RefId="0"/>
<MS>
<S N="Device">DeviceName7</S>
<S N="Mstatus">49</S>
</MS>
</Obj>
    </Objs>

CodePudding user response:

Since you're dealing with CLIXML files - i.e. XML-based files that contain .NET objects serialized by PowerShell - you can use Import-Clixml to import them, which makes comparing the resulting objects with Compare-Object easier:

$XMLPath = 'C:\Users\John.Doe\Desktop\Projects\Powershell\backend library conversion\TEST'

$filteredFile = "$XMLPath/Output/StatusErrorResultsFiltered.xml"
$resultFile = "$XMLPath/StatusErrorResults.xml"

Compare-Object (Import-Clixml $filteredFile) (Import-Clixml $resultFile) -Property Device, MStatus | 
  Select-Object * -ExcludeProperty SideIndicator | 
  Sort-Object -Unique -Property Device, Mstatus |
  Export-Clixml "$XMLPath\Output\UndefinedErrors.xml"

Note the need to remove the SideIndicator property from the output objects, which Compare-Object invariably adds to the output objects.

CodePudding user response:

Use Import-CliXMl, it will convert the XML to PS Objects and then you can can work on the unique part, then again Export-CliXml

$unitResults   = Import-Clixml "$XMLPath/StatusErrorResults.xml"
$filteredResults  = $(Import-Clixml "$XMLPath/Output/StatusErrorResultsFiltered.xml" | Select-Object -Property "Device", "Mstatus")

$unitResults  = $filteredResults
$endResult = $unitResults | Sort-Object -Property Device,Mstatus -Unique
$endResult | Export-Clixml -Path "$XMLPath\Output\UndefinedErrors.xml"
  • Related