web-dev-qa-db-fra.com

Déterminer XML Node existe

C'est probablement simple, mais j'essaie de déterminer si un nœud existe dans un document XML. Je pensais avoir trouvé une réponse dans ce post, Comment vérifier si un nœud existe ou non en utilisant PowerShell sans obtenir d'exception? , mais je ne l'ai pas fait fonctionner. Ceci est ma dernière tentative.

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
    }
   }

Toute aide serait grandement appréciée.

EDIT: Voici XML de mon fichier de test. J'ai besoin de découvrir EncKey existe ou note pour chaque fournisseur.

<?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

Il semble que j'utilisais la mauvaise syntaxe pour SelectSingleNode. Voici un exemple de travail.

[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

Merci à tous pour votre aide.

4
mack

La façon la plus simple à laquelle je peux penser est d'essayer d'écrire la valeur du nœud dans une variable, puis de voir si cette variable est nulle. Voici un exemple avec le fichier xml de librairie standard.

[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'
 }
} 

Donc pour votre script, je pense que ça pourrait être

$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

Utilisez XPath pour sélectionner les nœuds correspondants. InnerText est consultable par text(). Vous pouvez utiliser where-object, ou ? aussi; le comportement est un peu différent. Sans exemple de XML, il est difficile d'être plus précis. Utilisez XPath comme ça,

[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

À condition de charger l'objet $ xml en tant que XmlDocument à l'aide

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

Ensuite, vous pouvez le faire, ce qui est beaucoup plus simple:

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