我正在尝试使用powershell解析xml文件。我想打印每个节点及其子节点。我是xml解析的新手。
<?xml version="1.0" encoding="UTF-8"?>
<Inventory>
<Roles>
<Role Name="VirtualMachinePowerUser" Label="Virtual machine power user (sample)" Summary="Provides virtual machine interaction and configuration permissions">
<Privilege Name="Datastore.Browse" />
<Privilege Name="Global.CancelTask" />
<Privilege Name="ScheduledTask.Create" />
</Role>
<Role Name="VirtualMachineUser" Label="Virtual machine user (sample)" Summary="Provides virtual machine interaction permissions">
<Privilege Name="Global.CancelTask" />
<Privilege Name="ScheduledTask.Create" />
</Role>
我的下面的代码
[xml]$inputFile = Get-Content "C:\RolesnPer.xml"
$nodelist = $inputFile.Inventory.Roles.Role |Select-Object -Property Name
foreach ($Role in $nodelist)
{
$Role
$XMLprinterPath = $Role.selectSingleNode("Privilege").get_innerXml()
}
必填输出:
Name Privilege
VirtualMachinePowerUser Datastore.Browse
Global.CancelTask
ScheduledTask.Create
VirtualMachineUser Global.CancelTask
ScheduledTask.Create
但是我得到以下输出:
Name
----
VirtualMachinePowerUser
Method invocation failed because [Selected.System.Xml.XmlElement] does not contain a method named 'selectSingleNode'.
At C:\Mandy\Code\transformation.ps1:25 char:1
+ $XMLprinterPath = $Role.selectSingleNode("Privilege").get_innerXml()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (selectSingleNode:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
VirtualMachineUser
Method invocation failed because [Selected.System.Xml.XmlElement] does not contain a method named 'selectSingleNode'.
At C:\Mandy\Code\transformation.ps1:25 char:1
+ $XMLprinterPath = $Role.selectSingleNode("Privilege").get_innerXml()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (selectSingleNode:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
答案 0 :(得分:2)
Deadrobot's helpful answer可以正确诊断您的问题(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
cmdlet可以直接对文件进行操作,以使用XPath查询提取匹配的节点。
可以通过$_.Node
脚本块内的ForEach-Object
访问每个匹配的节点,PowerShell方便地将XML元素节点的子元素和属性公开为直接属性,因此{{1 }}报告.Name
属性的值,Name
返回所有.Privilege
个子元素作为数组,并感谢member enumeration来访问它们的Privilege
属性返回其所有.Name
属性的数组。
Name
是PSv3 +语法糖,用于使用哈希表语法构造自定义对象。
注意:虽然输出格式不是您要求的 ,但是输出对象 (而不是使用字符串格式)为您为以后的程序处理提供了更大的灵活性。
如果您确实需要问题中指定的精确输出格式:
[pscustomobject] @{ ... }
答案 1 :(得分:1)
之所以会这样,是因为第2行上的Select-Object
创建了一个不是xml的新对象。
我不是处理XML的专家,所以也许有更好的方法,但是我会对其进行编码以获得所需的输出:
[xml]$inputFile = Get-Content "C:\RolesnPer.xml"
$Nodelist = $inputFile.SelectNodes("//Role")
$ParsedOutput = @()
foreach ($Role in $Nodelist) {
$Name = $Role.Name
$Privilege = $Role.Privilege |Select-Object -ExpandProperty name
$Obj = New-Object -TypeName psobject
$Obj | Add-Member -MemberType NoteProperty -Name Name -Value $Name
$Obj | Add-Member -MemberType NoteProperty -Name Privilege -Value $Privilege
$ParsedOutput += $Obj
}
$ParsedOutput
答案 2 :(得分:1)
我知道已经提供了有关访问元素数据的答案,但是本文主要是针对输出格式要求:
$inputFile = [xml](Get-Content "C:\RolesnPer.xml")
$nodes = $inputFile.Inventory.Roles.Role | Select-Object -Property Name,Privilege
$NameColWidth = ($nodes.name | Foreach-Object { $_.length } | Sort-Object -Desc)[0] + 2
$FormattedOutput = @("{0,-$NameColWidth}{1}" -f "Name","Privilege") -as [collections.arraylist]
foreach ($node in $nodes) {
$null = $FormattedOutput.Add(("{0,-$NameColWidth}{1}" -f $node.name,($node.privilege.name | Select-Object -First 1)))
$node.Privilege | Select -expand Name -skip 1 | Foreach-Object {
$null = $FormattedOutput.Add(("{0,-$NameColWidth}{1}" -f " ",$_))
}
}
$FormattedOutput
如果只希望PowerShell对象数组具有两个属性(名称和特权)而不进行格式化,则只需要前两行。然后输出变量$nodes
。