首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Powershell字典添加不正确

Powershell字典添加不正确
EN

Stack Overflow用户
提问于 2020-08-14 02:42:41
回答 2查看 97关注 0票数 0

我有一个xml文件,如下所示。

代码语言:javascript
复制
<Packages>
  <package name="testR0" testversion="1.0.0.0" type="A">
    <package name="testR1" testversion="1.0.0.1" type="A">
    </package>
    <package name="testR2" testversion="1.1.0.0" type="A">
        <package name="testR3" testversion="1.1.1.0" type="B">
          <package name="testR4" testversion="1.1.1.1" type="C">
          </package>
          <package name="testR5" testversion="1.1.1.2" inc="true" type="C">
          </package>
          <package name="testR6" testversion="1.1.1.3" inc="true"  type="C">
          </package>
        </package>
   </package>
  </package>
</Packages>

需要将两个给定包名的测试版本和类型添加到字典中。如果我传递TestR0TestR3,那么它应该添加来自TestR2TestR3以及TestR5TestR6的测试版本和类型,其中inc=true。因此,生成的字典应该如下所示

代码语言:javascript
复制
{[1.1.0.0, A],[1.1.1.0, B],[1.1.1.2, C],[1.1.1.3, C]}

但是,即使我得到了值,字典也没有正确填充。它就像下面给出的那样。只有[1.1.0.0, A]出现在字典中

代码语言:javascript
复制
{[1.1.0.0, A]},[1.1.1.0, B],[1.1.1.2, C],[1.1.1.3, C]

我的代码如下所示

代码语言:javascript
复制
 function Get-Listver {

PROCESS {
    
    [xml] $versionInfo = Get-Content -Raw -Path "C:\test\test.xml" 
  
    $firstXML = Select-Xml -Xml $versionInfo -XPath "//*[@name='testR0']"
   
    $secondXML = Select-Xml -Xml $versionInfo -XPath "//*[@name='testR3']"
      
   $packagecollection = Get-AllPackageVersion $secondXML.Node $firstXML.Node 
    return $packagecollection
     }
  }


 function Get-AllPackageVersion {
[CmdletBinding()]
param (
    $secondXML,
    $firstXML
)
process {
  
    $packagecollection = New-Object System.Collections.Generic.Dictionary"[String,String]"
    
    if($secondXML.type -eq 'B'){
        $preReq = $secondXML.ChildNodes | Where-Object {$_.inc -eq "true"}
        if($preReq)
        {

        foreach($pq in $preReq)
        {
            $testver = $pq.testversion
            $testtyp = $pq.type
            $packagecollection.Add("$testver", "$testtyp")
        }
    }
    }
    
    $testver = $secondXML.testversion
    $testtyp = $secondXML.type
    $packagecollection.Add("$testver", "$testtyp")

    if($secondXML.ParentNode.Name -ne $firstXML.ParentNode.Name -and $secondXML.ParentNode.Name -ne $firstXML.Name){
        Get-AllPackageVersion $secondXML.ParentNode $firstXML 
    }

   
    if ($packagecollection.count -gt 1) 
    {
        $packagecollection = $packagecollection.GetEnumerator() | sort -Property key
    }
    return $packagecollection;
  }
 }

  Get-Listver

结果:

EN

回答 2

Stack Overflow用户

发布于 2020-08-15 05:16:49

尝试对脚本进行以下修改:

代码语言:javascript
复制
function Get-AllPackageVersion {
    [CmdletBinding()]
    param (
        $secondXML,
        $firstXML
    )
    process {
        if($secondXML.type -eq 'B'){
            $preReq = $secondXML.ChildNodes | Where-Object {'inc' -in $_.psobject.Properties.Name -and $_.inc -eq "true"}
            if($preReq) {
                foreach($pq in $preReq) {
                    $testver = $pq.testversion
                    $testtyp = $pq.type
                    $packagecollection.Add("$testver", "$testtyp")
                }
            }
        }
        $testver = $secondXML.testversion
        $testtyp = $secondXML.type
        $packagecollection.Add("$testver", "$testtyp")
    
        if($secondXML.ParentNode.Name -ne $firstXML.ParentNode.Name -and
           $secondXML.ParentNode.Name -ne $firstXML.Name){
            Get-AllPackageVersion $secondXML.ParentNode $firstXML 
        }
    }
}

function Get-Listver {
  PROCESS {
    [xml] $versionInfo = Get-Content -Raw -Path "C:\test\test.xml" 

    $firstXML  = Select-Xml -Xml $versionInfo -XPath "//*[@name='testR0']"
    $secondXML = Select-Xml -Xml $versionInfo -XPath "//*[@name='testR3']"

    $packagecollection = New-Object System.Collections.Generic.Dictionary"[String,String]"
    Get-AllPackageVersion $($secondXML.Node) $($firstXML.Node)
    return $packagecollection
  }
}

Get-Listver

输出(没有理由对Dictionary类型的对象进行“可视”排序):

代码语言:javascript
复制
$x = .\SO\63401378.ps1; $x; $x.Count, $x.GetType().Name

Key     Value
---     -----
1.1.1.2 C    
1.1.1.3 C    
1.1.1.0 B    
1.1.0.0 A    
4
Dictionary`2
票数 0
EN

Stack Overflow用户

发布于 2020-08-15 05:27:05

扩展@JosefZ的注释,你从你的函数中输出了4个项目,但是你得到了一些混合的类型:

问题在于,这取决于您是否访问此代码路径:

代码语言:javascript
复制
if ($packagecollection.count -gt 1) 
{
    $packagecollection = $packagecollection.GetEnumerator() | sort -Property key
}

在函数的末尾返回一个DictionarySystem.Object[]数组。

在您的特定示例中,输出中的第一项(testR2)没有命中代码路径,因此您得到一个包含一项的字典,但是testR3命中该代码路径并输出一个包含3项(testR3testR5testR6)的System.Object[]数组,该数组被展开并附加到输出中。

解决方案是确保返回一致的类型,而不管字典中有多少项。要做到这一点,一种方法是始终对字典进行排序,以便将其强制放入一个数组中,而不管其中有多少个条目。

更改上面的代码片段以删除if

代码语言:javascript
复制
$packagecollection = $packagecollection.GetEnumerator() | sort -Property key

现在你得到了:

顺便说一句,您的代码在复查时有点混乱,因为您混合了对Get-AllPackageVersion $secondXML.ParentNode $firstXML的递归调用的隐式输出和通过return $packagecollection;的cmdlet输出,并且您的隐式输出是在构建$packagecollection的过程中生成的。如果您将if($secondXML.ParentNode.Name ...块移到函数的顶部,以便更清楚地表明它首先被写入到输出管道中,则可能更容易阅读。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63401378

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档