Полезный ответ Deadrobot правильно диагностирует вашу проблему (Select-Object
испускает [pscustomobject]
экземпляров, а не узлов XML), но есть более простое решение:
Select-Xml -LiteralPath C:\RolesnPer.xml '//Role' | ForEach-Object {
[pscustomobject] @{
Name = $_.Node.Name
Privilege = $_.Node.Privilege.Name
}
}
Выше приведено:
Name Privilege
---- ---------
VirtualMachinePowerUser {Datastore.Browse, Global.CancelTask, ScheduledTask.Create}
VirtualMachineUser {Global.CancelTask, ScheduledTask.Create}
Объяснение:
Командлет Select-Xml
может напрямую работать с файлами для извлечения совпадающих узлов с запросами XPath.
Каждый соответствующий узел может быть доступен через $_.Node
внутри блока сценария ForEach-Object
, и PowerShell удобно представляет дочерние элементы и атрибуты узлов элементов XML как прямые свойства, так что .Name
сообщает значение Name
attribute и .Privilege
возвращают все Privilege
дочерние элементы в виде массива, и, благодаря перечислению членов , доступ к их свойству .Name
возвращает массив всех их Name
атрибутов.
[pscustomobject] @{ ... }
- это синтаксический сахар PSv3 + для создания пользовательского объекта с использованием синтаксиса хэш-таблицы.
Примечание. Хотя выходной формат равен , а не , в точности то, что вы просили , , вывод объектов (вместо использования форматирования строк) дает вам большую гибкость для последующей программной обработки .
Если вам нужен точный формат вывода , указанный в вашем вопросе :
# The format string to use with the -f operator below.
# The first column is 30 chars. wide; adjust as needed.
$fmtStr = '{0,-30} {1}'
# Output the header line.
$fmtStr -f 'Name', 'Privilege'
# Query the XML document and output the data lines.
Select-Xml -LiteralPath t.xml '//Role' | ForEach-Object {
$name = $_.Node.Name
foreach ($priv in $_.Node.Privilege.Name) {
$fmtStr -f $name, $priv
$name = ''
}
}