0

我需要首先测试一个 XML 文件的重复元素属性,即具有相同属性值的元素。然后我需要将这些相同的属性与另一个数组进行比较。

给定的 XML

<Definitions>
    <Sets>
        <Set id='S1' />
    </Sets>
    <Package>
        <Package id='P1' />
        <Package id='P2' />
    </Package>
</Definitions>

我可以用

$a = $xml.SelectNodes('//Package').id

构建一个 id 数组。我发现这个帖子有一个来自 Dale Qiao 的答案,看起来它应该可以工作。即

$a=@(1,2,3,1,2)
$b=$a | select –unique
Compare-object –referenceobject $b –differenceobject $a

但是当我像这样为我的场景修改它时

$a = @($invalidXML.SelectNodes('//Package').id)
$b=$a | select –unique
Compare-object –referenceobject $b –differenceobject $a

我收到一个错误Compare-Object : Cannot bind argument to parameter 'DifferenceObject' because it is null.$a不是空的,它是预期的 id 列表。

所以,首先要解决问题所在。其次,有人可以解释第二行发生了什么,$b=$a | select –unique. 我从未见过像这样通过管道传输的变量赋值的结果。我认为发生的事情并非如此,因为我认为 $b = (Select-Object -InputObject $a –unique) 会是相同的,没有管道,但事实并非如此。$b在那种情况下实际上仍然相同,$a这对我来说毫无意义。Select-Object但话虽如此,我对在管道中使用而不是在管道中使用时表现不同有一些模糊的回忆。当所有人都出去时,这令人沮丧。

编辑:不是Select-ObjectSort-Object就像我在这里问的那样。因此,仍然想知道为什么在使用 XML 时即使使用管道也会失败,并且想知道是否有类似的方法可以使用 .NET 而不是管道来选择唯一项目,因为与其他问题一样,我发现管道经常像糖蜜一样慢,并且对可读性不是特别好,所以总是在寻找其他选项并在它真的是唯一的,或者有时更高效的方法时回退到管道。

EDIT2:所以,我可能已经回答了我自己的问题。在基础上为什么它不能在前面工作,问题是我得到的数组真的是 a [System.Object],如果我真的遇到其他情况,比如[System.Collections.Generic.List[String]],那么Compare-Object可以使用它。如果我使用该链接中的技术进行排序,我可以避免管道Sort-Object,并且还可以转换结果。也就是说,不确定这个

$a = [System.Collections.Generic.List[String]]@($invalidXML.SelectNodes('//Package').id)
$b = [System.Collections.Generic.List[String]][System.Collections.Generic.SortedSet[String]]::new($a, [System.StringComparer]::InvariantCultureIgnoreCase)
Compare-object –referenceobject $b –differenceobject $a

确实提高了可读性。:) 当我使用只有 128 个字符的数组进行测试时,它的性能更高,大约是管道版本所需时间的 25%。管道需要整整 2 秒,但即使是 .NET 方法也需要半秒,这是不可行的,因为这将在初始化时发生很多次。是时候寻找加快速度的方法了。

编辑#3:Doh。我对每个测试进行了 1000 次迭代,以获得更大的数字进行比较。这不太可能在初始化时重复超过 100 次,即使是流水线方法也只需要 0.2 秒。所以我怀疑我可以根据可读性来专门选择。而且我可能只是让 .NET 更频繁地看到它,并附上解释我为什么使用它的评论,意味着我会记住它。:)

编辑#4:Doh。很好地提醒我自己,即使是最微妙的格式也是多么重要,尤其是在累的时候。 $b=$a | select –unique对我来说真的很奇怪。就像$b=$a被管道传输到的结果一样select –unique。但是,添加一些空格,$b = $a | select –unique突然意味着$b等于的结果$a | select –unique。很高兴几天后我在早上看到了这个。:) 争论我是否应该真正使用它,至少在脚本中。

$b = ($a | select-object –unique)
4

1 回答 1

0

I believe its failing because of using '| select –unique'. If you try '| Get-Unique' you should yield better results. Example below, see picture for results.

Here's How To Find Duplicates In XML Array

The XML Data File I Used

<Computers>
    <Computer>
        <Name>SRV-01</Name>
        <Ip>127.0.0.1</Ip>
        <Include>true</Include>
    </Computer> 
    <Computer>
        <Name>SRV-02</Name>
        <Ip>192.168.0.102</Ip>
        <Include>false</Include>
    </Computer> 
    <Computer>
        <Name>SRV-03</Name>
        <Ip>192.168.0.103</Ip>
        <Include>true</Include>
    </Computer> 
        <Computer>
        <Name>SRV-03</Name>
        <Ip>192.168.0.103</Ip>
        <Include>False</Include>
    </Computer>
</Computers>

Example Of Commands Used To Find Duplicate IP Addresses In XML File

[xml]$xmltest = Get-Content -Path  C:\temp\xmlfiles\test.xml
$xmltest.Computers.Computer

$a = $xmltest.Computers.Computer.ip
$a

$b = $xmltest.Computers.Computer.ip | Get-Unique
$b

##=> - Difference in destination object.
##<= - Difference in reference (source) object.
##== - When the source and destination objects are equal.

Compare-object -referenceobject $b -differenceobject $a

enter image description here

于 2021-12-05T11:01:36.140 回答