2013-12-06 6 views
7

Это, вероятно, просто, но я пытаюсь определить, существует ли узел в документе XML. Я думал, что нашел ответ в этом посте, How to check whether a node exists or not using powershell without getting exception?, но я не получил его на работу. Это моя последняя попытка.Определить существующий XML-узел

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

Любая помощь была бы принята с благодарностью.

EDIT: Вот 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> 
+0

Не могли бы вы предоставить пониженную тестовый пример для выпуска ? Что-то мы можем вставить в наш любимый редактор Powershell и поиграть с ним? – Neolisk

ответ

0

Оказывается, что я использовал неправильный синтаксис для 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 

Спасибо всем за помощь.

+0

Согласно моим тестам, SelectSingleNode чувствителен к регистру, если только не существует способа изменить его поведение. – Jay

1

Используйте 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 
3

Самый простой способ, которым я могу думать о том, чтобы попытаться записать значение узла переменной, а затем, чтобы увидеть, если эта переменная равна нулю. Вот пример со стандартным 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 
    } 
} 
+0

Спасибо Алекс. Это похоже на то, что я пытался сделать, но если $ vendor.EncKey не существует, я получаю исключение: ** Свойство EncKey не может быть найдено на этом объекте. Убедитесь, что он существует. ** и я никогда не попадаю в «else» часть инструкции. – mack

+0

Вы можете сократить это с помощью "if ($ vendor.EncKey) {" - также, это не зависит от регистра, по сравнению с SelectSingleNode, который не работал для меня. У меня не было никаких исключений. – Jay

1

условии, что вы загрузите объект $ XML как XmlDocument с помощью

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

Тогда вы можете сделать это, что гораздо проще:

if ($vendor.encKey -ne $null) { 
    # does exist 
} else { 
    # does not exist 
} 
Смежные вопросы