I have a script that compares objects and writes them to 3 new XMLs based on if they are ==, =>, or <=.
The issue I ma trying to solve is that the team that is sending the XML is not sorting repeatable fields so I get false positives.
My goal is to have the children groups below to be sorted.
Meaning:
I want the child tags sorted both/multiple in order. The order doesn’t really matter as I will be sorting both compare objects so when my if statements compare the objects the order will be the same.
[xml]$ReferenceXML = @"
<Rt>
<CUDATE>
<RecId>SDFGHJKLJGHJKHL764830SLCOLU2002</RecId>
<PtySpData>
<DtTm>2023-09-04T18:35:38Z</DtTm>
<RptNtty>
<NUM>548787777BYUC1BFR06N38</NUM>
</RptNtty>
<CP>
<RCP>
<NameNum>
<NUM>54656789300UE5IV80HGVDE63</NUM>
</NameNum>
<Ntr>
<F>
<Df>YUIO</Df>
</F>
</Ntr>
</RCP>
<OCP>
<NameNum>
<Name>
<NUM>549300BV8YXI1GVJKG40</NUM>
</Name>
</NameNum>
</OCP>
<NttyRpt>
<NUM>549300UE5IV677868780HGVDE63</NUM>
</NttyRpt>
</CP>
</PtySpData>
<Ln>
<SctLn>
<EDt>2023-09-04</EDt>
<UnqIdr>QWERTYUIOPKHJKHL</UnqIdr>
<MAg>
<Pt1>
<Pt2>DERP</Pt2>
</Pt1>
<Vrn>2356</Vrn>
</MAg>
</SctLn>
</Ln>
<Coll>
<SctLnd>
<Cosd>
<Asst>
<Sct>
<Name>GB123456789</Name>
<Type>DFGHJJK</Type>
<NmnlV>
<NV>
<A Ddy="NPD">12</A>
</NV>
</NmnlV>
<UP>
<MVal>
<A Ddy="NPD">500</A>
</MVal>
</UP>
<kktV>
<Amt Ddy="NPD">501</Amt>
</kktV>
<Ql>YUIU</Ql>
<Mtty>2010-10-04</Mtty>
<Dsr>
<NameNum>
<NUM>549300CDO03FKIZ7UK53</NUM>
</NameNum>
<JursCty>TX</JursCty>
</Dsr>
<Pt>
<Cd>HOUS</Cd>
</Pt>
<HrMrgn>99</HrMrgn>
<AvblUuse>true</AvblUuse>
</Sct>
<Sct>
<Name>GB123456789</Name>
<Type>FFGHXX</Type>
<NmnlV>
<NV>
<A Ddy="NPD">5</A>
</NV>
</NmnlV>
<UP>
<MntryVal>
<A Ddy="NPD">100</A>
</MntryVal>
</UP>
<MktVal>
<A Ddy="NPD">101</A>
</MktVal>
<Ql>OIUY</Ql>
<Mtty>2023-10-04</Mtty>
<Dsr>
<NameNum>
<NUM>549300CDO03FKIZ7UK53</NUM>
</NameNum>
<JursCty>KS</JursCty>
</Dsr>
<Pt>
<Cd>OKIY</Cd>
</Pt>
<HrMrgn>99</HrMrgn>
<AvblUuse>true</AvblUuse>
</Sct>
</Asst>
<NetInd>false</NetInd>
</Cosd>
</SctLnd>
</Coll>
</CUDATE>
</Rt>
"@
$test = $ReferenceXML.Rt.CUDATE.Coll.SctLnd.Cosd.Asst
Foreach($Node in $test){
If ($Node.ChildNodes.Count -gt 1){
$Node | Select-Xml 'AsstTp' | Select-Object -expand Node | sort '#text'
Write-Host "Node value: $($Node.OuterXml)"
}
}
To make it clearer I would like the XML file to look like this:
[xml]$ReferenceXML = @"
<Rt>
<CUDATE>
<RecId>SDFGHJKLJGHJKHL764830SLCOLU2002</RecId>
<PtySpData>
<DtTm>2023-09-04T18:35:38Z</DtTm>
<RptNtty>
<NUM>548787777BYUC1BFR06N38</NUM>
</RptNtty>
<CP>
<RCP>
<NameNum>
<NUM>54656789300UE5IV80HGVDE63</NUM>
</NameNum>
<Ntr>
<F>
<Df>YUIO</Df>
</F>
</Ntr>
</RCP>
<OCP>
<NameNum>
<Name>
<NUM>549300BV8YXI1GVJKG40</NUM>
</Name>
</NameNum>
</OCP>
<NttyRpt>
<NUM>549300UE5IV677868780HGVDE63</NUM>
</NttyRpt>
</CP>
</PtySpData>
<Ln>
<SctLn>
<EDt>2023-09-04</EDt>
<UnqIdr>QWERTYUIOPKHJKHL</UnqIdr>
<MAg>
<Pt1>
<Pt2>DERP</Pt2>
</Pt1>
<Vrn>2356</Vrn>
</MAg>
</SctLn>
</Ln>
<Coll>
<SctLnd>
<Cosd>
<Asst>
<Sct>
<Name>GB123456789</Name>
<Type>FFGHXX</Type>
<NmnlV>
<NV>
<A Ddy="NPD">5</A>
</NV>
</NmnlV>
<UP>
<MntryVal>
<A Ddy="NPD">100</A>
</MntryVal>
</UP>
<MktVal>
<A Ddy="NPD">101</A>
</MktVal>
<Ql>OIUY</Ql>
<Mtty>2023-10-04</Mtty>
<Dsr>
<NameNum>
<NUM>549300CDO03FKIZ7UK53</NUM>
</NameNum>
<JursCty>KS</JursCty>
</Dsr>
<Pt>
<Cd>OKIY</Cd>
</Pt>
<HrMrgn>99</HrMrgn>
<AvblUuse>true</AvblUuse>
</Sct>
<Sct>
<Name>GB123456789</Name>
<Type>DFGHJJK</Type>
<NmnlV>
<NV>
<A Ddy="NPD">12</A>
</NV>
</NmnlV>
<UP>
<MVal>
<A Ddy="NPD">500</A>
</MVal>
</UP>
<kktV>
<Amt Ddy="NPD">501</Amt>
</kktV>
<Ql>YUIU</Ql>
<Mtty>2010-10-04</Mtty>
<Dsr>
<NameNum>
<NUM>549300CDO03FKIZ7UK53</NUM>
</NameNum>
<JursCty>TX</JursCty>
</Dsr>
<Pt>
<Cd>HOUS</Cd>
</Pt>
<HrMrgn>99</HrMrgn>
<AvblUuse>true</AvblUuse>
</Sct>
</Asst>
<NetInd>false</NetInd>
</Cosd>
</SctLnd>
</Coll>
</CUDATE>
</Rt>
"@
If you look that the first XML you see that the first and second Sct have been switched. Now I am not sure what I would sort on because Sct are the same but there is a difference DFGHJJK.
I would like to capture both and sort them based on but I need that sort to be with the original and not a copy.
Here is the compare function that has been set up:
Function Compare-XML-Files {
[CmdletBinding()]
Param (
$Path = $(Get-Location),
$ReferenceFile,
$ComparedFile
)
Begin {
Set-Location $Path
Write-Host "Comparing XML Values"
$MatchedValues = New-Object System.Collections.Generic.List[PSObject]
$ActualReportedValues = New-Object System.Collections.Generic.List[PSObject]
$ExpectsReportedValues = New-Object System.Collections.Generic.List[PSObject]
$ReferenceXML = [xml]''
$ComparedXML = [xml]''
$MatchedFileNew = $ReferenceFile -replace '.xml','_Matched_Both.xml'
$ActualFileNew = $ReferenceFile -replace '.xml','_Actual_Only.xml'
$ExpectsFileNew = $ReferenceFile -replace '.xml','_Expects_Only.xml'
}
Process {
$ReferenceXML.Load($("$ExpectsFile"))
$Header = $ReferenceXML.BizData.OuterXml -replace "<Trad>.*", '<Trad>'
$Footer = $ReferenceXML.BizData.OuterXml -replace ".*</Trad>", '</Trad>'
$RefTradData = $ReferenceXML.BizData.Pyld.Document.ChildNodes.TradData
$RefTrades = $RefTradData.ChildNodes.OuterXml -replace "\sxmlns*.+?>", '>'
$ComparedXML.Load($("$ActualFile"))
$ComparedHeader = $ComparedXML.BizData.OuterXml -replace "<Trad>.*", '<Trad>'
$ComparedFooter = $ComparedXML.BizData.OuterXml -replace ".*</Trad>", '</Trad>'
$ComTradData = $ComparedXML.BizData.Pyld.Document.ChildNodes.TradData
$ComTrades = $ComTradData.ChildNodes.OuterXml -replace "\sxmlns*.+?>", '>'
$test = $ReferenceXML.Rt.CUDATE.Coll.SctLnd.Cosd.Asst
Foreach($Node in $test){
If ($Node.ChildNodes.Count -gt 1){
$Node | Select-Xml 'AsstTp' | Select-Object -expand Node | sort '#text'
Write-Host "Node value: $($Node.OuterXml)"
}
}
}
$XMLObjects = @{
ReferenceObject = $RefTrades
DifferenceObject = $ComTrades
}
$ComparedXML = Compare-Object @XMLObjects -IncludeEqual
ForEach ($Result in $ComparedXML) {
If ($Result.SideIndicator -eq '==') {
$ComparedValue = [ordered] @{
Trade = [string]$Result.InputObject
}
$null = $MatchedValues.Add($(New-Object PSObject -Property $ComparedValue))
}
ElseIf ($Result.SideIndicator -eq '=>') {
$ComparedValue = [ordered] @{
Trade = [string]$Result.InputObject
}
$null = $ActualReportedValues.Add($(New-Object PSObject -Property $ComparedValue))
}
ElseIf ($Result.SideIndicator -eq '<=') {
$ComparedValue = [ordered] @{
Trade = [string]$Result.InputObject
}
$null = $ExpectsReportedValues.Add($(New-Object PSObject -Property $ComparedValue))
}
Else {
Write-Host $($Result.SideIndicator) $($Result.InputObject)
}
}
If ($MatchedValues) {
$Content = ForEach ($value in $MatchedValues.Trade) {$value}
$xml = $($Header),$($Content),$($Footer)
Set-Content -Path $MatchedFileNew -Value $xml
}
If ($ActualReportedValues) {
$Content = ForEach ($value in $ActualReportedValues.Trade) {$value}
$xml = $($Header),$($Content),$($Footer)
Set-Content -Path $ActualFileNew -Value $xml
}
If ($ExpectsReportedValues) {
$Content = ForEach ($value in $ExpectsReportedValues.Trade) {$value}
$xml = $($Header),$($Content),$($Footer)
Set-Content -Path $ExpectsFileNew -Value $xml
}
}
End {
}
} #Compare-XML-Files