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 ge开发者_Python百科t all the users that have a "Bar" as a friend? (In this example it would be Foo,Foo3).
Should I use xpath?
Thanks!
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}
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)
Yes, XPath would be sufficient for that!
Check Powershell to test your XPath to see how it can be done.
Whilst the other answers are perfectly acceptable, I personally prefer to do it using SelectNodes
.
Given the question XML in a variable $xml
, the following will return an array.
$names = $xml.SelectNodes("//User[contains(Friends/Friend/@Name, 'Bar')]/@Name")
The $names
variable is an XPathNodeList
which is derived from XmlNodeList
and will output the following.
#text
-----
Foo
Foo3
If you want to grab the values, you can either iterate or grab by index. For example, $names[1].Value
will produce Foo3
.
精彩评论