将占位符替换为PowerShell字典中的实际值

时间:2017-03-08 01:01:37

标签: xml powershell dictionary powershell-v2.0

以下是示例xml文件:

 <configuration>
  <environment id="Development">
    <type>Dev</type>
    <client>Arizona</client>
    <dataSource>Local</dataSource>
    <path>App_Data\%%type%%\%%client%%_%%dataSource%%</path>
    <targetmachines>
      <targetmachine>
        <name>Any</name>
        <remotedirectory>D:\Inetpub\Test</remotedirectory>
      </targetmachine>
    </targetmachines>
  </environment>
 </configuration>

我正在尝试使用以下脚本将上述xml文件转换为PowerShell字典。

[System.Xml.XmlDocument] $configxml = Get-Content xmlfile
$environmentId = "Development"
$keyValuePairs = New-Object "System.Collections.Generic.Dictionary``2[System.String,System.String]"
$configxml.SelectNodes("//configuration/environment[@id='$($environmentId)']//*[not(*)]") | `
    ForEach-Object {
                    if($_.ParentNode.ToString() -ne "targetmachine")
                    {

                        $keyValuePairs.Add($_.Name.ToLower(), $_.InnerText)
                    }
                }

Write-Output $keyValuePairs

我得到了以下输出,这是预期的。

Key                         Value
-----                       -----
type                        Dev
client                      Arizona
dataSource                  Local
path                        App_Data\%%type%%\%%client%%_%%dataSource%%

但是在将元素转换为Key值对之后,我想用实际值替换占位符。换句话说,元素“Path”有3个占位符,它们是

1. type
2. client
3. dataSource

基本上占位符是指以两个百分比开头和结尾的字符串(%% xyz %%)。因此,在用实际值替换占位符后,我需要跟随输出:

Key                         Value
-----                       -----
type                        Dev
client                      Arizona
dataSource                  Local
path                        App_Data\Dev\Arizona_Local

有人可以帮助我如何使用PowerShell实现这一目标。提前谢谢。

1 个答案:

答案 0 :(得分:1)

通常,在使用xml或csv数据发布示例时,在此处使用字符串来表示数据而不是引用其他人没有的文件是有帮助的。

这样的东西可以用来实现你的结果。

$xmldata = @"
<configuration>
    <environment id="Development">
    <type>Dev</type>
    <client>Arizona</client>
    <dataSource>Local</dataSource>
    <path>App_Data\%%type%%\%%client%%_%%dataSource%%</path>
    <targetmachines>
        <targetmachine>
        <name>Any</name>
        <remotedirectory>D:\Inetpub\Test</remotedirectory>
        </targetmachine>
    </targetmachines>
    </environment>
</configuration>
"@

[System.Xml.XmlDocument] $configxml = [xml]$xmldata
$environmentId = "Development"
$keyValuePairs = New-Object "System.Collections.Generic.Dictionary``2[System.String,System.String]"
$configxml.SelectNodes("//configuration/environment[@id='$($environmentId)']//*[not(*)]") | `
    ForEach-Object {
                    if($_.ParentNode.ToString() -ne "targetmachine")
                    {

                        $keyValuePairs.Add($_.Name, $_.InnerText)
                    }
                }

"BEFORE---->"
Write-Output $keyValuePairs

# A static way...
#$keyValuePairs.path = $keyValuePairs.path -replace '%%type%%', $keyValuePairs.type
#$keyValuePairs.path = $keyValuePairs.path -replace '%%client%%', $keyValuePairs.client
#$keyValuePairs.path = $keyValuePairs.path -replace '%%datasource%%', $keyValuePairs.datasource

# Something more dynamic
$m = [Regex]::Matches($keyValuePairs.path,"%%(.+?)%%*")
$m | % {
    $tag = $_.Groups[1].Value
    $keyValuePairs.path = $keyValuePairs.path -replace "%%$tag%%", $($keyValuePairs.$tag)
}

"AFTER---->"
Write-Output $keyValuePairs

注意,如果你想要一些完全动态的东西,可以通过一些其他方法来获取所有占位符,比如带有捕获的正则表达式,但根据问题陈述这似乎是不必要的。