Как перебирать XML в Powershell?
У меня есть этот XML-документ в текстовом файле:
<?xml version="1.0"?>
<Objects>
<Object Type="System.Management.Automation.PSCustomObject">
<Property Name="DisplayName" Type="System.String">SQL Server (MSSQLSERVER)</Property>
<Property Name="ServiceState" Type="Microsoft.SqlServer.Management.Smo.Wmi.ServiceState">Running</Property>
</Object>
<Object Type="System.Management.Automation.PSCustomObject">
<Property Name="DisplayName" Type="System.String">SQL Server Agent (MSSQLSERVER)</Property>
<Property Name="ServiceState" Type="Microsoft.SqlServer.Management.Smo.Wmi.ServiceState">Stopped</Property>
</Object>
</Objects>
Я хочу выполнить итерацию каждого объекта и найти DisplayName
и ServiceState
. Как мне это сделать? Я пробовал всевозможные комбинации и изо всех сил стараюсь это исправить.
Я делаю это, чтобы преобразовать XML в переменную:
[xml]$priorServiceStates = Get-Content $serviceStatePath;
где $serviceStatePath
- это имя файла xml, показанное выше. Затем я подумал, что могу сделать что-то вроде:
foreach ($obj in $priorServiceStates.Objects.Object)
{
if($obj.ServiceState -eq "Running")
{
$obj.DisplayName;
}
}
И в этом примере мне нужна строка, выводимая с помощью SQL Server (MSSQLSERVER)
Ответы
Ответ 1
PowerShell имеет встроенные функции XML и XPath.
Командлет Select-Xml можно использовать с запросом XPath для выбора узлов из объекта XML, а затем
.Node. '# Text' для доступа к значению node.
[xml]$xml = Get-Content $serviceStatePath
$nodes = Select-Xml "//Object[Property/@Name='ServiceState' and Property='Running']/Property[@Name='DisplayName']" $xml
$nodes | ForEach-Object {$_.Node.'#text'}
Или короче
[xml]$xml = Get-Content $serviceStatePath
Select-Xml "//Object[Property/@Name='ServiceState' and Property='Running']/Property[@Name='DisplayName']" $xml |
% {$_.Node.'#text'}
Ответ 2
Вы также можете сделать это без приведения [xml]. (Хотя xpath - это мир сам по себе. Https://www.w3schools.com/xml/xml_xpath.asp)
$xml = (select-xml -xpath / -path stack.xml).node
$xml.objects.object.property
Или только это, xpath чувствителен к регистру:
$xml = (select-xml -xpath /Objects/Object/Property -path stack.xml).node