Условно для пустого набора SelectNodes - PullRequest
0 голосов
/ 27 декабря 2018

С учетом 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>

Я хочу проверить наличие атрибута ОС, чтобы можно было по-разному обрабатывать получение значения, когда есть два узла, дифференцированных по значению этого атрибута, без атрибута вообще.

Я бы подумал, что это сработает, с соответствующими значениями для двух переменных.

if ($script:pxResources.SelectNodes("//Product[@id='$product']/$resource[@os]")) {

Однако, это возвращает true, даже когда ни один узел не выбран.Я могу использовать

if ($script:pxResources.SelectNodes("//Product[@id='$product']/$resource[@os]").count -gt 0) {

, но это кажется неуклюжим.Есть ли лучший способ справиться с этим, или тестирование на пустой набор - единственный вариант?

Ответы [ 2 ]

0 голосов
/ 27 декабря 2018

Существует, поэтому подход, при котором вы не используете 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)"
    }
}

Это выдаст

'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 
0 голосов
/ 27 декабря 2018

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}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...