You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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"

说明

  1. 新增ConvertTo-EntryObject函数,将每个<Obj>节点转换为包含Device和Mstatus属性的自定义对象,确保对比的是完整条目而非零散节点。
  2. 使用ForEach-Object遍历所有<Obj>节点,转换为统一格式的对象集合。
  3. 此时Compare-Object可正确识别两组对象的差异,输出预期的独有条目(即DeviceName6和DeviceName7对应的条目)。

内容的提问来源于stack exchange,提问作者BCon995

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 11:20:37