Powershell xml xpath
В Powershell,
предположим, что у меня есть следующий xml:
<Users>
<User Name="Foo">
<Friends>
<Friend Name="Bar"/>
</Friends>
</User>
<User Name="Foo2" />
<User Name="Foo3">
<Friends>
<Friend Name="Bar"/>
</Friends>
</User>
</Users>
Как я могу получить всех пользователей, у которых есть "Бар" в качестве друга?
(В этом примере это будет Foo, Foo3).
Должен ли я использовать xpath?
Спасибо!
Ответы
Ответ 1
Я предпочитаю использовать XPath в эти дни. Я столкнулся с проблемами с помощью адаптера xls PowerShell, которые раздражают, как столкновение имен на 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}
Ответ 2
В этом случае я бы использовал XPath. @TomWij предоставил правильный xpath.
Если выражение xpath будет слишком сложным, я бы наверняка использовал "классический" подход.
$x.Users.User | ? { $_.Friends.Friend.Name -eq 'Bar' }
(в этом случае, если у вас нет режима script, не имеет значения, что нет элемента Friends
. $_.Friends
вернет $null
и $null.Friend
возвращает $null
как ну и т.д. Итак, наконец, $null -eq 'Bar'
возвращает false и элемент удаляется Where-Object)
Ответ 3
Да, XPath будет достаточно для этого!
Отметьте Powershell, чтобы проверить ваш XPath, чтобы узнать, как это можно сделать.
Ответ 4
Хотя другие ответы вполне приемлемы, я лично предпочитаю делать это с помощью SelectNodes
.
Учитывая вопрос XML в переменной $xml
, следующий будет возвращать массив.
$names = $xml.SelectNodes("//User[contains(Friends/Friend/@Name, 'Bar')]/@Name")
Переменная $names
- это XPathNodeList
, которая получена из XmlNodeList
и выдаст следующее.
#text
-----
Foo
Foo3
Если вы хотите получить значения, вы можете выполнить итерацию или получить по индексу. Например, $names[1].Value
будет производить Foo3
.