在 Powershell 中获取第一个元素的属性

Get first element's attribute in Powershell

我正在编写一个自动站点备份 powershell 脚本。

我在从 appcmd.exe 获得的 [xml] 强制转换变量中有以下 xml:

<application path="/" applicationPool="komplus.ua-PROD">     
  <virtualDirectoryDefaults />  
  <virtualDirectory path="/" physicalPath="C:\WEB\PROD\komplus.ua" />       
</application>
<application path="/kb" applicationPool="komplus.ua-PROD" enabledProtocols="http, https">
  <virtualDirectoryDefaults /> 
  <virtualDirectory path="/" physicalPath="C:\WEB\PROD\komplus.ua\kb" />
</application>

xml在变量$xml中输入。

我需要获取第一个应用程序元素中 VirtualDirectory 元素的 physicalPath 属性的值。

我尝试了多种选择,包括自定义 Get-XmlElement 函数,但似乎无法获取值。

目前我有:

 $selectResult = $xmlInput.application.virtualDirectory | Select physicalPath

但是$selectResult 为空。

请协助解析出我需要的值是正确的

更新

这是我用来获取完整路径的完整函数:

function GetPhysicalPath ([String]$siteName) {


function Get-PipelineInput
{            
    end {
        $inputAsVar = 'Current input is:' + $input
        write-host "##teamcity[message text='$inputAsVar']"

        write-host "##teamcity[message text='About to cast to xml']"
        $xmlInput = [xml]@"<root>$input</root>"@

        write-host "##teamcity[message text='Cast to xml finished.']"                

        $selectResult = $xml.root.Application | Where-Object { $_.path -eq '/' } | ForEach-Object { $_.virtualDirectory.physicalPath }

        write-host "##teamcity[message text='$selectResult']"

        return $selectResult

        #$node = Get-XmlNode -XmlDocument $xmlInput -NodePath "application.virtualDirectory"

        #$nodeAsVar = 'Single node is:' + $node
        #write-host "##teamcity[message text='$nodeAsVar']"
        #if ($node -eq $null) { return $null }

        #return $node.physicalPath
    }
}

$appCmd = "$Env:SystemRoot\system32\inetsrv\appcmd.exe"

return & $appCmd list app /site.name:"$siteName" /config | Get-PipelineInput
}

您的 xml 无效。 XML 需要根元素。如果您的 "xml"-file 丢失了它,那么您可以像这样将文件的内容自己包装在根元素中:

Get-ChildItem -Path C:\Users\Frode\Desktop -Filter "appcmd*" | ForEach-Object {

    #Wrap "xml" in root element and convert to xml-type
    $xml = [xml]@"
<root>
$([System.IO.File]::ReadAllText($_.FullName))
</root>
"@

    #Get first physicalPath
    $xml.root.Application[0].virtualDirectory.physicalPath
}

C:\WEB\PROD\komplus.ua

如果您有 PowerShell 3 或更新版本,您可以将 $([System.IO.File]::ReadAllText($_.FullName)) 替换为更友好的 $(Get-Content -Path $_.FullName -Raw))。但是,ReadAllText() 通常更快,所以我还是会使用它。

如果您想要根应用程序,您可能应该搜索它而不是猜测它是第一个元素。你可以尝试这样的事情:

Get-ChildItem -Path C:\Users\Frode\Desktop -Filter "appcmd*" | ForEach-Object {

    #Wrap "xml" in root element and convert to xml-type
    $xml = [xml]@"
<root>
$(Get-Content -Path $_.FullName -Raw))
</root>
"@

    #Get root app's physicalPath
    $xml.root.Application | Where-Object { $_.path -eq '/' } | ForEach-Object { $_.virtualDirectory.physicalPath }
}

如果您直接从 appcmd.exe 获取 xml-content(存储在变量中),则修改如下:

$outputfromappcmd = appcmd.exe something something

#Wrap "xml" in root element and convert to xml-type
$xml = [xml]"<root>$outputfromappcmd </root>"

#Get first physicalPath
$xml.root.Application | Where-Object { $_.path -eq '/' } | ForEach-Object { $_.virtualDirectory.physicalPath }