web-dev-qa-db-ja.com

XMLの決定Node Exists

これはおそらく単純ですが、XMLドキュメントにノードが存在するかどうかを確認しようとしています。この投稿で回答を見つけたと思いました ノードが存在するかどうか、例外を取得せずにPowerShellを使用していないかどうかを確認する方法は? が動作しませんでした。これが私の最新の試みです。

foreach ($vendor in $xml.Vendors.Vendor| Where-Object  {$_.Type -match "Send"}) {
    $NodeExists = $vendor.SelectSingleNode($vendor.EncKey)
    if ($NodeExists -ne $null) {
        # Do something
    }
    else {
       # something else
    }
   }

どんな助けでも大歓迎です。

編集:これは私のテストファイルのXMLです。 EncKeyが存在することを確認するか、各ベンダーについてメモする必要があります。

<?xml version="1.0" encoding="UTF-8"?>
    <!-- Vendors we will send and retreive files from Get-Send means we will get a file and send them a file Send means we will only send them a file-->
    <Vendors>
        <Vendor Type="Get-Send">
            <Name>Vendor1</Name>            
            <RemotePath>/Remote/Path1/</RemotePath>
            <EncKey>pgpenc.key</EncKey>
        </Vendor>
        <Vendor Type="Send">
            <Name>Vendor2</Name>            
            <RemotePath>/Remote/Path2/</RemotePath> 
            <!-- This one has no EncKey -->         
        </Vendor>
    </Vendors>
17
mack

SelectSingleNodeに間違った構文を使用していたようです。これが実際の例です。

[xml]$xml = @'
<?xml version="1.0" encoding="UTF-8"?>
    <!-- Vendors we will send and retreive files from Get-Send means we will get a file and send them a file Send means we will only send them a file-->
    <Vendors>
        <Vendor Type="Get-Send">
            <Name>Vendor1</Name>            
            <RemotePath>/Remote/Path1/</RemotePath>
            <EncKey>pgpenc.key</EncKey>
        </Vendor>
        <Vendor Type="Send">
            <Name>Vendor2</Name>            
            <RemotePath>/Remote/Path2/</RemotePath> 
            <!-- This one has no EncKey -->         
        </Vendor>
    </Vendors>
'@

foreach ($vendor in $xml.Vendors.Vendor| Where-Object  {$_.Type -match "Send"}) {
    $NodeExists = $vendor.SelectSingleNode("./EncKey")
    if ($NodeExists -ne $null) {
        write-Host "EncKey is null"
    }
    else {
       write-Host "EncKey is not null"
    }
   }

EncKey is null
EncKey is not null

皆さんの助けに感謝します。

4
mack

私が考えることができる最も簡単な方法は、ノード値を変数に書き込んでから、その変数がnullかどうかを確認することです。これは、標準の書店のxmlファイルの例です。

[xml]$bookstore = Get-Content .\bookstore.xml
foreach ($book in $bookstore.bookstore.book | Where-Object {$_.Type -match "novel"}) {
 $NodeExists = $book.author
 if($NodeExists){
  Write-Host $book.author
 }
 else{
  Write-Host 'No Author'
 }
} 

だからあなたのスクリプトについては、

$NodeExists = $null
foreach ($vendor in $xml.Vendors.Vendor| Where-Object  {$_.Type -match "Send"}) {
 $NodeExists = $vendor.EncKey
 if ($NodeExists) {
  # Do something
 }
 else {
  # something else
  }
}
10
Alex McKenzie

XPathを使用して、一致するノードを選択します。 InnerTextはtext()で検索できます。 where-object、または?も使用できます。動作は少し異なります。サンプルXMLがないと、より正確にするのは困難です。そのようにXPathを使用し、

[xml]$doc = @'
<root>
<Vendors>
<Vendor>
<Type>Send</Type>
</Vendor>
<Vendor>
<Type>Receive</Type>
</Vendor>
</Vendors>
</root>
'@

# Xpath query will return a NodeList, even if no match is found
$node1 = $doc.SelectNodes("//Vendor/Type[text() = 'Send']")
$node2 = $doc.SelectNodes("//Vendor/Type[text() = 'Sent']")
$node1.Count
1
$node2.Count
0

# where-object will return $null if no match is found
$node1 = $doc.SelectNodes("//Vendor/Type") | ? { $_.InnerText -eq "Send" }
$node2 = $doc.SelectNodes("//Vendor/Type") | ? { $_.InnerText -eq "Sent" }

$node1 -eq $null
False
$node2 -eq $null
True
4
vonPryz

$ xmlオブジェクトをXmlDocumentとしてロードした場合

$xml = new-object System.Xml.XmlDocument
$xml.LoadXml( (get-content $pathToXmlFile) )

次に、これを行うことができます。これははるかに簡単です。

if ($vendor.encKey -ne $null) {
  # does exist
} else {
  # does not exist
}
3
Alex Fairchild