Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine XML Node Exists

This is probably simple, but I'm trying to determine if a node exists in an XML document. I thought I found an answer in this post, How to check whether a node exists or not using powershell without getting exception?, but I didn't get it to work. This is my latest attempt.

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

Any help would be greatly appreciated.

EDIT: Here is XML from my test file. I need to find out of EncKey exists or note for each vendor.

<?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>
like image 437
mack Avatar asked Dec 06 '13 21:12

mack


People also ask

How do I check if a node exists in XML?

You can iterate through each and every node and see if a node exists. doc. Load(xmlPath); XmlNodeList node = doc. SelectNodes("//Nodes/Node"); foreach (XmlNode chNode in node) { try{ if (chNode["innerNode"]==null) return true; //node exists //if ...

How to check XML node exists or not in Java?

How to check if xml node exists? To verify if node or tag exists in XML content, you can execute an xpath expression against DOM document for that XML and count the matching nodes. matching nodes > zero – XML tag / attribute exists. matching nodes <= zero – XML tag / attribute does not exist.

What is node XML?

Everything in an XML document is a node. For example, the entire document is the document node, and every element is an element node. Root node. The topmost node of a tree. In the case of XML documents, it is always the document node, and not the top-most element.

What is XmlNode in C#?

XmlNode is the base class in the . NET implementation of the DOM. It supports XPath selections and provides editing capabilities. The XmlDocument class extends XmlNode and represents an XML document. You can use XmlDocument to load and save XML data.


3 Answers

The easiest way I can think of is to try to write the node value to a variable, and then to see if that variable is null. Here's an example with the standard bookstore xml file.

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

So for your script, I would think it might be

$NodeExists = $null
foreach ($vendor in $xml.Vendors.Vendor| Where-Object  {$_.Type -match "Send"}) {
 $NodeExists = $vendor.EncKey
 if ($NodeExists) {
  # Do something
 }
 else {
  # something else
  }
}
like image 181
Alex McKenzie Avatar answered Sep 30 '22 17:09

Alex McKenzie


It appears that I was using the wrong syntax for SelectSingleNode. Here is a working example.

[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

Thanks everyone for your help.

like image 22
mack Avatar answered Sep 30 '22 16:09

mack


Use XPath to select matching nodes. InnerText is searchable by text(). You can use where-object, or ? too; behaviour is a bit different. Without sample XML it's hard to be more precise. Use XPath like so,

[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
like image 36
vonPryz Avatar answered Sep 30 '22 16:09

vonPryz