问题
Following is the sample xml file:
<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>
I'm trying to convert the above xml file into a PowerShell dictionary using following script.
[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
Im getting following output, which is expected.
Key Value
----- -----
type Dev
client Arizona
dataSource Local
path App_Data\%%type%%\%%client%%_%%dataSource%%
But After converting the elements into Key value pairs, I want to replace the placeholders with actualy values. In other words, element "Path" has 3 placeholders, they are
1. type
2. client
3. dataSource
Basically placeholders means the strings which starts and ends with two percents (%%xyz%%). So, I need following output after replacing placeholders with actual values:
Key Value
----- -----
type Dev
client Arizona
dataSource Local
path App_Data\Dev\Arizona_Local
Can someone please help me how can I achive this using PowerShell. Thanks in advance.
回答1:
In general, when posting an example with xml or csv data, it is helpful to use here strings to represent the data instead of referencing a file that others do not have.
Something like this can be used to achieve your result.
$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
Note, if you wanted something totally dynamic in nature, it can be done by getting all the placeholders by some other method, like a regex with capture, but that seemed unnecessary based on the problem statement.
来源:https://stackoverflow.com/questions/42661150/replace-placeholders-with-actual-values-in-powershell-dictionary