Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Trying to extract child node values from xml in Powershell

I have the following xml:

<?xml version="1.0"?>
<AdminDirectorUsers>
    <Users>
        <User>
            <UserName>PC1</UserName>
            <Installation>
                <Products>
                    <Product>
                        <ProductID>Product1</ProductID>
                        <Selected>Yes</Selected>
                    </Product>
                    <Product>
                        <ProductID>Product2</ProductID>
                        <Selected>No</Selected>
                    </Product>
                    <Product>
                        <ProductID>Product3</ProductID>
                        <Selected>No</Selected>
                    </Product>
                    <Product>
                        <ProductID>Product4</ProductID>
                        <Selected>Yes</Selected>                        
                    </Product>
                </Products>
            </Installation>
        </User>
        <User>
            <UserName>PC2</UserName>
            <Installation>
                <Products>
                    <Product>
                        <ProductID>Product1</ProductID>
                        <Selected>Yes</Selected>
                    </Product>
                    <Product>
                        <ProductID>Product2</ProductID>
                        <Selected>Yes</Selected>
                    </Product>
                    <Product>
                        <ProductID>Product3</ProductID>
                        <Selected>No</Selected>
                    </Product>
                    <Product>
                        <ProductID>Product4</ProductID>
                        <Selected>Yes</Selected>                        
                    </Product>
                </Products>
            </Installation>
        </User>
    </Users>
</AdminDirectorUsers>

I would like to loop through and extract a list of each UserName with all ProductIDs that has a sibling node Selected with a value of Yes, while ignoring the values of No.

$path = 'C:\Temp\test.xml'
$xml = New-Object -TypeName XML
$xml.Load($Path)
$UserNode = $xml.SelectNodes('//User')
$ProductNode = $xml.SelectNodes('//Product')

foreach ($PC in $usernode)
{
  $PC.username
  foreach($Node in $ProductNode){
    # Test if selected == 'yes'
    if($Node.Selected -eq 'yes') {
      $Node.ProductID
    }
  }
}

My output is:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

PC1
Product1
Product4
Product1
Product2
Product4
PC2
Product1
Product4
Product1
Product2
Product4

…but I’m looking for:

PC1
Product1
Product4
PC2
Product1
Product2
Product4

I’ve tried many ways to do this but nothing seems to work. What am I missing?

>Solution :

Change the second XPath expression used for the Product/ProductID to only get the descendants of a specific <User> element, by anchoring against . (the "current node"):

# Enumerate each `<User>` element
$xml |Select-Xml '//User' |%{
  # Grab the exact username value
  $username = $_.Node.UserName

  # Then enumerate all descendant `<ProductID>` nodes who has a sibling `<Selected>Yes</Selected>` and attach username
  $_.Node |Select-Xml './/ProductID[../Selected[. = "Yes"]]' |Select -Expand Node |Select @{Name='Username';Expression={$username}},InnerText
}

(I’m using Select-Xml here but this works the same with the SelectNodes() method)

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading