PowerShell对比两个XML文件,输出独有条目(排除Description字段)
问题:对比两个PowerShell导出的XML文件,提取独有条目(排除Description字段)
我有两个格式一致的XML文件,能在PowerShell正常读取显示,但需要对比StatusErrorResultsFiltered.xml和StatusErrorResults.xml,输出仅在其中一个文件存在的独有条目,同时排除description字段。
当前代码
$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"
当前问题
生成的UndefinedErrors.xml只显示一个包含Device和Mstatus的节点,但没有有效数据,内容如下:
<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>
问题原因及修正代码
问题根源
原代码错误地提取了单个<S>节点(比如单独的Device或Mstatus节点),而非将每个<Obj>节点转换为包含Device和Mstatus属性的完整对象。Compare-Object无法对零散节点进行有效对比,导致输出空值。
修正后的代码
$XMLPath = "C:\Users\John.Doe\Desktop\Projects\Powershell\backend library conversion\TEST\" # 读取两个XML文件 $filteredResults = [xml](Get-Content "$XMLPath/Output/StatusErrorResultsFiltered.xml") $unitResults = [xml](Get-Content "$XMLPath/StatusErrorResults.xml") # 将每个Obj节点转换为包含Device和Mstatus的自定义对象 function ConvertTo-EntryObject { param([xml.XmlElement]$ObjNode) $device = ($ObjNode.MS.S | Where-Object { $_.N -eq "Device" }).'#text' $mstatus = ($ObjNode.MS.S | Where-Object { $_.N -eq "Mstatus" }).'#text' [PSCustomObject]@{ Device = $device Mstatus = $mstatus } } $originalEntries = $unitResults.Objs.obj | ForEach-Object { ConvertTo-EntryObject $_ } $filteredEntries = $filteredResults.Objs.obj | ForEach-Object { ConvertTo-EntryObject $_ } # 对比两组对象,找出独有条目 $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"
说明
- 新增
ConvertTo-EntryObject函数,将每个<Obj>节点转换为包含Device和Mstatus属性的自定义对象,确保对比的是完整条目而非零散节点。 - 使用
ForEach-Object遍历所有<Obj>节点,转换为统一格式的对象集合。 - 此时
Compare-Object可正确识别两组对象的差异,输出预期的独有条目(即DeviceName6和DeviceName7对应的条目)。
内容的提问来源于stack exchange,提问作者BCon995
相关产品推荐
相关产品推荐

