Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell to get attribute values from XML with multiple attributes

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!

like image 844
user888818 Avatar asked Nov 04 '13 20:11

user888818


1 Answers

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
like image 93
Frode F. Avatar answered Oct 18 '22 14:10

Frode F.