确定 XML 节点存在

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20433932/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 11:56:56  来源:igfitidea点击:

Determine XML Node Exists

xmlpowershellpowershell-2.0

提问by mack

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.

这可能很简单,但我正在尝试确定 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
    }
   }

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。我需要找出每个供应商的 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>

采纳答案by mack

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

看来我对 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

Thanks everyone for your help.

感谢大家的帮助。

回答by Alex McKenzie

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 文件的示例。

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

回答by vonPryz

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,

使用 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

回答by Alex Fairchild

Provided you load the $xml object as an XmlDocument using

如果您使用以下方法将 $xml 对象加载为 XmlDocument

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

Then you can do this, which is much simpler:

然后你可以这样做,这要简单得多:

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