views:

322

answers:

3

In Powershell, suppose I have the following xml:

  <Users>
    <User Name="Foo">
      <Friends>
        <Friend Name="Bar"/>
      </Friends>
    </User>
    <User Name="Foo2" />
    <User Name="Foo3">
      <Friends>
        <Friend Name="Bar"/>
      </Friends>
    </User>
  </Users>

How can I get all the users that have a "Bar" as a friend? (In this example it would be Foo,Foo3).

Should I use xpath?

Thanks!

+1  A: 

Yes, XPath would be sufficient for that!

Check Powershell to test your XPath to see how it can be done.

TomWij
/Users/User[contains(./Friends/Friend/@Name, "Bar")]
TomWij
Please provide better link. This article doesn't use new cmdlet `Select-Xml` from V2. It is much more handy: `Select-Xml -xml $xml -xpath '/Users/User[contains(./Friends/Friend/@Name, "Bar")]' | select -exp node`
stej
I'm not able to edit my comment any more, so here is a link to Jaykul's post: http://huddledmasses.org/xpath-and-namespaces-in-powershell/
stej
I didn't know of that yet, thank you...
TomWij
+2  A: 

In this case I would use XPath as well. @TomWij provided the correct xpath.

In case that the xpath expression would be too complicated, I would for sure used the 'classic' approach.

$x.Users.User | ? { $_.Friends.Friend.Name -eq 'Bar' }

(in this case if you don't have script mode on, it doesn't matter that there is no Friends element. $_.Friends will return $null and $null.Friend returns $null as well and so on. So finally $null -eq 'Bar' returns false and the element is removed by Where-Object)

stej
+3  A: 

I have a preference for using XPath these days. I've run into issues using PowerShell's xml adapter that are annoying like the name collision on item:

$xml = [xml]@'
  <Users> 
    <User Name="Foo"> 
      <Friends> 
        <Friend Name="Bar"/> 
      </Friends> 
    </User> 
    <User Name="Foo2" /> 
    <User Name="Foo3"> 
      <Friends> 
        <Friend Name="Bar"/> 
      </Friends> 
    </User> 
  </Users> 
'@

Select-Xml '//User[contains(Friends/Friend/@Name, "Bar")]' $xml |%{$_.Node.Name}
Keith Hill