PowerShell to get attribute values from XML with multiple attributes
Asked Answered
M

1

7

The following XML file is one Object node of the output from the command Get-ClusterGroup run from a 2008 R2 Failover Cluster with PowerShell 2:

<?xml version="1.0"?>
<Objects>
  <Object>
    <Property Name="Cluster">Cluster1</Property>
    <Property Name="IsCoreGroup">False</Property>
    <Property Name="OwnerNode">Node1</Property>
    <Property Name="State">Offline</Property>
    <Property Name="Name">SAP PL1</Property>
    <Property Name="Description" />
    <Property Name="PersistentState">1</Property>
    <Property Name="FailoverThreshold">4294967295</Property>
    <Property Name="FailoverPeriod">6</Property>
    <Property Name="AutoFailbackType">1</Property>
    <Property Name="FailbackWindowStart">4294967295</Property>
    <Property Name="FailbackWindowEnd">4294967295</Property>
    <Property Name="Priority">1</Property>
    <Property Name="DefaultOwner">4294967295</Property>
    <Property Name="AntiAffinityClassNames" />
    <Property Name="Id">a5ff557f-c81a-43aa-bdb9-e09d0a1103df</Property>
  </Object>
</Objects>

The full file has three more Object nodes similar to this. Two of those nodes have the value "False" in the "IsCoreGroup" attribute and the other two are "True". What I am trying to do is get the value of the "Name" property and other attributes from the Object nodes that have the value of "False" in the "IsCoreGroup" attribute.

I have tried a number of ways to get this attribute but can't figure out how to drill down into the sibling attributes.

Here's what I have so far:

[xml]$file = get-content C:\Admin\ClusterGroups.xml
$xmlProperties = $file.SelectNodes("/Objects/Object/Property")
Foreach ($xmlProperty in $xmlProperties) {
    $strName = ($xmlProperty | Where-Object {$_.Name -eq "IsCoreGroup" }).InnerXml
    If ($strName -eq "False")
    {
    Echo $xmlProperty
    }
}

This gives me the following:

Name                                      #text                                    
----                                      -----                                    
IsCoreGroup                               False      

But I can't figure out how to get the sibling properties

I tried backing up a level with:

[xml]$file = get-content C:\Admin\ClusterGroups.xml
$xmlObjects = $file.SelectNodes("/Objects/Object")
Foreach ($xmlObject in $xmlObjects) {
    $strCoreGroup = ($xmlObject | Where-Object {$_.Property.Name -eq "IsCoreGroup" }).InnerXml
    If ($strCoreGroup -eq "False")
    {
    Echo $xmlObject
    }
}

But that's not getting me anywhere.

Any help is greatly appreciated!

Millais answered 4/11, 2013 at 20:9 Comment(0)
G
6

You need to access the parentnode if you're variable points at a property-element. Since you need to find a property element where the name is a attribute-value, I prefer using xpath to do this.

$xmlProperties = $file.SelectNodes("/Objects/Object/Property")
Foreach ($xmlProperty in $xmlProperties) {
    $strName = ($xmlProperty | Where-Object {$_.Name -eq "IsCoreGroup" }).InnerXml
    If ($strName -eq "False")
    {
        # .. means parent node. So the xpath goes up one level from property, and searches for the new property you want.
        $xmlProperty.SelectSingleNode('../Property[@Name="Name"]').InnerXml
    }
}

You could also have done $xmlproperty.parentnode.whateveryouwant.

Personally I'd use xpath to search for the right objects to begin with and retrieve them at object-level, so you can easily access the other properties in the object-node without going up a level.

$file.SelectNodes('/Objects/Object[Property[@Name="IsCoreGroup"]="False"]') | % { 
    #Foreach object with IsCoreGroup = false, get value of property with Cluster1 as Name attribute
    $_.SelectSingleNode('Property[@Name="Cluster"]').innerxml
}

Cluster1
Gerena answered 4/11, 2013 at 20:39 Comment(2)
Only downside is XPath queries are case-sensitive so if you have two documents that aren't consistent with their casing, the XPath query would work in one and fail in the other.Ohmmeter
That is true. But for computer-generated files, the case is often static(at least when the files are new and not only updated). :)Gerena

© 2022 - 2024 — McMap. All rights reserved.