1

What is the most efficient way to output the users in the format below:

Vinny,Blue|Red

Mike,Blue

LeeRoy,Blue

Jenny,Blue|Red

Deborah,Red

Using the following code:

<Section1 name="colors" category="colors">
  <Section2 name="Blue" category="color">
    <Section3 name="Users" category="users">
     <Section4 name="Vinny" category="user"></Section4>
     <Section4 name="Mike" category="user"></Section4>
     <Section4 name="LeeRoy" category="user"></Section4>
     <Section4 name="Jenny" category="user"></Section4>
    </Section3>
  </Section2>
  <Section2 name="Red" category="color">
    <Section3 name="Users" category="users">
      <Section4 name="Vinny" category="user"></Section4>
      <Section4 name="Jenny" category="user"></Section4>
      <Section4 name="Deborah" category="user"></Section4>
    </Section3>
  </Section2>
</Section1>

With the condition that if the users (Section4) appear in multiple colors (Section 2), they are separated by the | character.

At first I dumped all the colors in one array, then was going to dump all the users in another array, then I got stuck trying to do a couple of things...

2 Answers 2

3

Here's one way to achieve this. That way, all your users and colors are linked together in one list.

In the example below, I am making use of the Select-XML statement to get the users, the Select-object to select multiple properties and finally I am using calculated properties to use change the property name returned and also get the color node.

[xml]$xml = @'
<Section1 name="colors" category="colors">
  <Section2 name="Blue" category="color">
    <Section3 name="Users" category="users">
     <Section4 name="Vinny" category="user"></Section4>
     <Section4 name="Mike" category="user"></Section4>
     <Section4 name="LeeRoy" category="user"></Section4>
     <Section4 name="Jenny" category="user"></Section4>
    </Section3>
  </Section2>
  <Section2 name="Red" category="color">
    <Section3 name="Users" category="users">
      <Section4 name="Vinny" category="user"></Section4>
      <Section4 name="Jenny" category="user"></Section4>
      <Section4 name="Deborah" category="user"></Section4>
    </Section3>
  </Section2>
</Section1>
'@


$value = Select-Xml -Xml $xml -XPath '//Section4'

$UsersArray = $value | select @{'n'='user';'e'={$_.Node.name}},@{'n'='color';'e'={$_.Node.ParentNode.ParentNode.name}}

# You can now manipulate your results as you see fit
$UsersArray | Sort user | ft

Useful references

The @{'n'='';'e'=''} shown in the example statement are shortcut for @{'name'='';'expression'=''}, which are Calculated properties. In your case, it allow us to get easily the color value once we are at the User level without any additional statement.

Select-XML reference for examples on how to use it.

Sign up to request clarification or add additional context in comments.

Comments

1

(very) ugly but gives the desired output

[xml]$xml = '<Section1 name="colors" category="colors">
    <Section2 name="Blue" category="color">
        <Section3 name="Users" category="users">
            <Section4 name="Vinny" category="user"></Section4>
            <Section4 name="Mike" category="user"></Section4>
            <Section4 name="LeeRoy" category="user"></Section4>
            <Section4 name="Jenny" category="user"></Section4>
        </Section3>
    </Section2>
    <Section2 name="Red" category="color">
        <Section3 name="Users" category="users">
            <Section4 name="Vinny" category="user"></Section4>
            <Section4 name="Jenny" category="user"></Section4>
            <Section4 name="Deborah" category="user"></Section4>
        </Section3>
    </Section2>
</Section1>'

$users = $xml.Section1.Section2.Section3.Section4.Name | Select-Object -Unique

foreach($user in $users) {
    $matchedColors = @()
    foreach($color in $xml.Section1.Section2.Name) {
        if($xml.Section1.Section2.Where({ $_.Name -eq $color }).Section3.Section4.Name -contains $user) {
            $matchedColors += $color
        }
    }
    "{0},{1}" -f $user, ($matchedColors -join "|")
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.