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

时间:2015-01-19 17:27:36

标签: xml 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位于变量$ xmlInput。

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

我尝试了多种选项,包括自定义Get-XmlElement功能,但似乎无法获得该值。

目前我有:

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

但$ selectResult为null。

请协助解析正确以获得我需要的值。

更新

这是我用来获取完整路径的完整功能:

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
}

1 个答案:

答案 0 :(得分:2)

您的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()通常更快,所以无论如何我都会使用它。

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

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内容,则修改如下:

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