给出这样的XML
<?xml version="1.0"?>
<Definitions>
<Products>
<Product_Group id="Revit">
<Product id="RVT2017">
<RSAccelerator>RSACCELERATOR2017</RSAccelerator>
<ShortcutPath os="6.0 6.1">C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Autodesk\Revit 2017</ShortcutPath>
<ShortcutPath os="6.2 6.3 10.0">C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Revit 2017</ShortcutPath>
</Product>
</Product_Group>
</Products>
</Definitions>
我想测试OS属性的存在,以便当有两个节点通过该属性值与完全没有属性进行区分时,我可以以不同的方式处理该值。
我以为这可以正常工作,并为两个变量设置适当的值。
if ($script:pxResources.SelectNodes("//Product[@id='$product']/$resource[@os]")) {
但是,即使没有选择任何节点,这也将返回true。我可以使用
if ($script:pxResources.SelectNodes("//Product[@id='$product']/$resource[@os]").count -gt 0) {
但是看起来很笨拙。有没有更好的方法来解决这个问题,还是测试空集是唯一的选择?
答案 0 :(得分:1)
AFAIK,您将始终必须进行测试,因为 SelectNodes
将返回 System.Xml.XPathNodeList
对象,即使PowerShell将其视为真实对象是空的。
同意添加一些代码进行测试并不是一件容易的事,但是AFAIK是必须的。
我首选的方法是 IsNullOrEmpty
:
[String]::IsNullOrEmpty(<thing>)
# example
$exp = $script:pxResources.SelectNodes("//Product[@id='$product']/$resource[@os]")
if (-not [String]::IsNullOrEmpty($exp)) {# do something}
答案 1 :(得分:0)
There's a;so the approach where you don't use XPath:
[xml]$xml = @"
<?xml version="1.0"?>
<Definitions>
<Products>
<Product_Group id="Revit">
<Product id="RVT2017">
<RSAccelerator>RSACCELERATOR2017</RSAccelerator>
<ShortcutPath os="6.0 6.1">C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Autodesk\Revit 2017</ShortcutPath>
<ShortcutPath os="6.2 6.3 10.0">C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Revit 2017</ShortcutPath>
<ShortcutPath os="">C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Anything\Revit 2017</ShortcutPath>
<ShortcutPath>C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Something\Revit 2017</ShortcutPath>
</Product>
</Product_Group>
</Products>
</Definitions>
"@
$product = "RVT2017"
$resource = "ShortcutPath"
($xml.Definitions.Products.Product_Group.Product | Where-Object { $_.id -eq $product }).$resource | ForEach-Object {
if ($null -eq $_.os) {
Write-Host "'os' attribute missing on $_"
}
elseif ([string]::IsNullOrWhiteSpace($_.os)) {
Write-Host "'os' attribute empty on element $($_.outerXml)"
}
else {
Write-Host "'os' = $($_.os) on element $($_.outerXml)"
}
}
This will output
'os' = 6.0 6.1 on element <ShortcutPath os="6.0 6.1">C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Autodesk\Revit 2017</ShortcutPath>
'os' = 6.2 6.3 10.0 on element <ShortcutPath os="6.2 6.3 10.0">C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Revit 2017</ShortcutPath>
'os' attribute empty on element <ShortcutPath os="">C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Anything\Revit 2017</ShortcutPath>
'os' attribute missing on C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Something\Revit 2017