PowerShell to get attribute values from XML with m

2019-06-19 02:39发布

问题:

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!

回答1:

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