todd1215 todd1215 - 3 months ago 8
PowerShell Question

Access XML attribute with powershell fails for one node but not another

So I have this function that I'm using to get the attribute 'type' from one of my XML nodes. There are at least two of these Nodes in the XML file.

The XML section looks like this

<config>
<local>
<setup>
<backup type="7Day"/>
<folder name="Backups" type="backup_root">
<folder name="DayTemplate" type="day_template">
<folder name="Logs"/>
<folder name="Objects">
<folder name="Applications"/>
</folder>
</folder>
</folder>
</setup>
</local>
</config>


In my function below I'm passing in the xml Object $xmlDoc.config.local.setup and then what 'type' I'm expecting to find. The usage would be something like

$type = Get-FolderNameByType -folders $xmlDoc.config.local.setup -type 'day_template'


The first folder type 'backup_root' I can see when debugging the code. If fails to match as expected but the second one 'day_template' never is found. The foreach loop skips right past it for some reason and I'm not sure why.

function Get-FolderNameByType
{
param
(
[Object]
$folders,

[Object]
$type
)
foreach ($folder in $folders.folder)
{
if ( $folder.type )
{
if ( $folder.type -eq $type )
{
return $folder.name.tostring()
}
}
}
}


I'm sure this issue has everything to do with how I'm parsing the XML and how it's actually organized in memory but I can't figure it out. Any help is much appreciated.

Answer

The problem is that you only enumerate the top-level folders but your folder structure is nested, therefore you only see 'backup_root'.
You can either call your function recursively or select all folder tags below your $folders node which could be done like so:

...
foreach ($folder in $folders.SelectNodes('//folder')) 
{
    if ($folder.type ...  

As the last one already uses a XPath expression, we could eliminate your loop altogether and rewrite your function like so

function Get-FolderNameByType  
{
  param
  (
    [Object]
    $folders,

    [Object]
    $type
  )
  $folders.SelectNodes("//folder[@type='$type']")
}
Comments