Roshan N
Roshan N

Reputation: 1053

Read XML Attribute values based on another attribute value in the same node using Powershell

I have a XML file file1.xml which has the data like below.

<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>

I Need a PowerShell script which will return the value of the Path attribute based on the Name attribute value.

Example:

If I pass the value "File4.rdl" it should return the value as "Folder76".

I Wrote the command to read the XML data and stored the data in an array $Test.

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

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

Write-Host $Test

I Wrote the below PowerShell script to perform the same.

$AttribureReportName = "File4.rdl"

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

As I have too many XML tags it was taking long time perform the operation. Is there any better way to do the same?

Upvotes: 0

Views: 170

Answers (2)

Tomalak
Tomalak

Reputation: 338326

First off, this is wrong:

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

Don't load XML files this way, this can cause encoding issues. XML parsers have a well thought-out automatic encoding detection mechanism. Get-Content does not have that, so there is a good chance that the XML file is loaded with the wrong encoding and data inside gets corrupted.

Use the XML parser to load the file.

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

After that, you can use XPath to pick the right node from the file. This will be much faster than writing any Powershell loops yourself (Where-Object also is a loop).

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

Upvotes: 2

Theo
Theo

Reputation: 61168

As your Name attribute should be compared in a Case-Insensitive mode, I suggest something like this:

[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
}

Upvotes: 2

Related Questions