使用Powershell读取基于同一节点中另一个属性值的XML属性值

时间:2019-01-16 10:23:09

标签: xml powershell

我有一个XML文件file1.xml,其数据如下所示。

<Tag1>
<Tag2>      
  <file Name="file1.rdl" Path="folder34" />
  <File Name="file2.rdl" Path="folder37" />
  <File Name="file3.rdl" Path="folder34" />
  <File Name="File4.rdl" Path="folder76" />
  <File Name="file5.rdl" Path="folder37" />
</Tag2>
</Tag1>

我需要一个PowerShell脚本,该脚本将基于Path属性值返回Name属性的值。

示例:

如果我传递值“ File4.rdl”,则应将其返回值为“ Folder76”。

我写了命令以读取XML数据并将数据存储在数组$Test中。

[xml]$XmlDocument = Get-Content "D:\Roshan\Testing\Test1.xml"

$Test = $XmlDocument.Tag1.Tag2.file | Select-Object Name, Path

Write-Host $Test

我编写了以下PowerShell脚本来执行相同的操作。

$AttribureReportName = "File4.rdl"

foreach ($item in $Test) {
    if ($item.Name -eq $AttribureReportName) {
        $FinalFolder = $item.Path
        Write-Output $FinalFolder 
    }
}

由于我的XML标记太多,因此执行该操作需要花费很长时间。有没有更好的方法可以做到这一点?

2 个答案:

答案 0 :(得分:2)

由于您的Name属性应在不区分大小写的模式下进行比较,因此建议如下:

[xml]$xml = @"
<Tag1>
<Tag2>      
  <file Name="file1.rdl" Path="folder34" />
  <File Name="file2.rdl" Path="folder37" />
  <File Name="file3.rdl" Path="folder34" />
  <File Name="File4.rdl" Path="folder76" />
  <File Name="file5.rdl" Path="folder37" />
</Tag2>
</Tag1>
"@

$AttribureReportName = "File4.rdl"

foreach ($item in ($xml.Tag1.Tag2.file | Where-Object {$_.Name -eq $AttribureReportName})) {
    $item.Path
}

答案 1 :(得分:2)

首先,这是错误的:

[xml]$XmlDocument = Get-Content "D:\Roshan\Testing\Test1.xml"

请勿以这种方式加载XML文件,这可能会导致编码问题。 XML解析器具有经过深思熟虑的自动编码检测机制。 Get-Content没有,所以很有可能XML文件加载了错误的编码,并且内部数据被破坏了。

使用XML解析器加载文件。

$XmlDocument = New-Object xml
$XmlDocument.Load("D:\Roshan\Testing\Test1.xml")

之后,可以使用XPath从文件中选择正确的节点。这比自己编写任何Powershell循环要快得多(Where-Object也是一个循环)。

$File = $XmlDocument.SelectSingleNode("/Tag1/Tag2/File[@Name = 'File4.rdl']")
Write-Host $File.Path