Last active
February 22, 2025 07:38
-
-
Save michaellwest/ad10b91ff6650f32171cc4db0262b5ff to your computer and use it in GitHub Desktop.
Pure PowerShell script to apply an XDT transform with a typicaly web.config found in ASP.Net.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Merge-XdtTransform { | |
<# | |
.SYNOPSIS | |
A function to apply Xml Configuration Transforms without the need for Microsoft.Web.XmlTransform.dll. | |
.NOTES | |
Michael West | |
.EXAMPLE | |
Merge-XdtTransform -Base $xmlBase -Transform $xmlTransform | |
#> | |
param( | |
[Parameter(Mandatory)] | |
[ValidateNotNull()] | |
[xml]$Base, | |
[Parameter(Mandatory)] | |
[ValidateNotNull()] | |
[xml]$Transform | |
) | |
$document = $Base.Clone() | |
try { | |
Write-Host "Processing Xdt Transforms" | |
#https://learn.microsoft.com/en-us/previous-versions/aspnet/dd465326(v=vs.110) | |
$namespaceManager = New-Object System.Xml.XmlNamespaceManager($transform.NameTable) | |
$namespaceManager.AddNamespace("xdt", "http://schemas.microsoft.com/XML-Document-Transform") | |
foreach ($transformNode in $transform.SelectNodes("//*[@xdt:Transform]", $namespaceManager)) { | |
$transformType = $transformNode.Attributes["xdt:Transform"] | |
$nodesToModify = & { | |
$xpath = "//$($transformNode.LocalName)" | |
$locator = $transformNode.Attributes["xdt:Locator"] | |
if($locator -and $locator.Value -like "Match*") { | |
#Locator="Match(comma-delimited list of one or more attribute names)" | |
#xdt:Locator="Match(key)" | |
$matchAttributeNames = $locator.Value.Replace("Match(","").Replace(")","").Split(",") | |
foreach($matchAttributeName in $matchAttributeNames) { | |
$matchAttributeValue = $transformNode.Attributes[$matchAttributeName].Value | |
$xpath += "[@$($matchAttributeName)='$($matchAttributeValue)']" | |
} | |
$document.SelectNodes($xpath) | |
} elseif($locator -and $locator.Value -like "XPath*") { | |
#Locator="XPath(XPath expression)" | |
#xdt:Locator="XPath(configuration/connectionStrings/add[@name='PaymentsContext'])" | |
$xpath = $locator.Value.Replace("XPath(","").Replace(")","") | |
$document.SelectNodes($xpath) | |
} elseif($locator -and $locator.Value -like "Condition*") { | |
#Locator="Condition(XPath expression)" | |
#xdt:Locator="Condition(@key='IsStaging')" | |
if ($locator.Value -match "Condition\((.+)\)") { | |
$condition = $matches[1] | |
$xpath += "[$($condition)]" | |
$document.SelectNodes($xpath) | |
} | |
} elseif (!$locator) { | |
$document.SelectSingleNode($xpath) | |
} | |
} | |
$keepProcessing = $true | |
$nodeQueue = New-Object System.Collections.Queue | |
@($nodesToModify) | ForEach-Object { $nodeQueue.Enqueue($_) > $null } | |
while($keepProcessing) { | |
$nodeToModify = if($nodeQueue.Count -gt 0) { $nodeQueue.Dequeue() } else { $null } | |
if($nodeQueue.Count -eq 0) { | |
$keepProcessing = $false | |
} | |
switch -Wildcard ($transformType.Value) { | |
"CommentOut" { | |
if(!$nodeToModify) { | |
Write-Host "- [CommentOut] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName) skipped" -ForegroundColor Yellow | |
continue | |
} | |
$parentNode = $nodeToModify.ParentNode | |
$comment = [string]::Concat(" ", $nodeToModify.OuterXml, " ") | |
$newNode = $document.CreateComment($comment) | |
Write-Host "- [CommentOut] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName)" -ForegroundColor Blue | |
$parentNode.InsertAfter($newNode, $nodeToModify) > $null | |
$parentNode.RemoveChild($nodeToModify) > $null | |
} | |
"SetAttributes*" { | |
if(!$nodeToModify) { | |
Write-Host "- [SetAttributes] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName) skipped" -ForegroundColor Yellow | |
continue | |
} | |
Write-Host "- [SetAttributes] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName)" -ForegroundColor Blue | |
$attributesToSet = $transformType.Value.Replace("SetAttributes","").Replace("(","").Replace(")","").Split(",", [System.StringSplitOptions]::RemoveEmptyEntries) | |
$attributeLookup = New-Object System.Collections.Generic.HashSet[string](@(,$attributesToSet)) | |
$transformNode.Attributes | ForEach-Object { | |
if ($_.Name -notlike "xdt:*" -and ($attributeLookup.Count -eq 0 -or $attributeLookup.Contains($_.Name))) { | |
$nodeToModify.SetAttribute($_.Name, $_.Value) > $null | |
} | |
} | |
} | |
"Replace" { | |
if(!$nodeToModify) { | |
Write-Host "- [Replace] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName) skipped" -ForegroundColor Yellow | |
continue | |
} | |
$parentNode = $nodeToModify.ParentNode | |
$newNode = $document.ImportNode($transformNode, $true) | |
$transformNode.Attributes | ForEach-Object { | |
if ($_.Name -like "xdt:*") { | |
$newNode.RemoveAttribute($_.Name) > $null | |
} | |
} | |
Write-Host "- [Replace] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName)" -ForegroundColor Blue | |
$parentNode.ReplaceChild($newNode, $nodeToModify) > $null | |
} | |
"Insert" { | |
$parentNode = $nodeToModify.ParentNode | |
if(!$parentNode) { | |
#Node is missing so let's get the parent. | |
$parentNode = $document.SelectSingleNode("//$($transformNode.ParentNode.LocalName)") | |
} | |
if(!$parentNode) { | |
Write-Host "- [Insert] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName) skipped" -ForegroundColor Yellow | |
continue | |
} | |
$newNode = $document.ImportNode($transformNode, $true) | |
$transformNode.Attributes | ForEach-Object { | |
if ($_.Name -like "xdt:*") { | |
$newNode.RemoveAttribute($_.Name) > $null | |
} | |
} | |
Write-Host "- [Insert] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName)" -ForegroundColor Blue | |
$parentNode.AppendChild($newNode) > $null | |
} | |
"InsertIfMissing" { | |
if($nodeToModify) { | |
Write-Host "- [InsertIfMissing] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName) skipped" -ForegroundColor Yellow | |
continue | |
} | |
$parentNode = $document.SelectSingleNode("//$($transformNode.ParentNode.LocalName)") | |
$newNode = $document.ImportNode($transformNode, $true) | |
$transformNode.Attributes | ForEach-Object { | |
if ($_.Name -like "xdt:*") { | |
$newNode.RemoveAttribute($_.Name) > $null | |
} | |
} | |
Write-Host "- [InsertIfMissing] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName)" -ForegroundColor Blue | |
$parentNode.AppendChild($newNode) > $null | |
} | |
"InsertBefore*" { | |
#Example: InsertBefore(/configuration/system.web/membership) | |
$parentNode = $nodeToModify.ParentNode | |
if(!$parentNode) { | |
#Node is missing so let's get the parent. | |
$parentNode = $document.SelectSingleNode("//$($transformNode.ParentNode.LocalName)") | |
} | |
if(!$parentNode) { | |
Write-Host "- [InsertBefore] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName) skipped" -ForegroundColor Yellow | |
continue | |
} | |
$path = $transformType.Value.Replace("InsertBefore(","").Replace(")","") | |
$beforeNode = $document.SelectSingleNode($path) | |
$newNode = $document.ImportNode($transformNode, $true) | |
$transformNode.Attributes | ForEach-Object { | |
if ($_.Name -like "xdt:*") { | |
$newNode.RemoveAttribute($_.Name) > $null | |
} | |
} | |
if ($beforeNode) { | |
Write-Host "- [InsertBefore] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName) before $($beforeNode.LocalName)" -ForegroundColor Blue | |
$parentNode.InsertBefore($newNode, $beforeNode) > $null | |
} else { | |
Write-Host "- [InsertBefore] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName)" -ForegroundColor Blue | |
$parentNode.AppendChild($newNode) > $null | |
} | |
} | |
"InsertAfter*" { | |
#Example: InsertAfter(/configuration/system.webServer) | |
$parentNode = $nodeToModify.ParentNode | |
if(!$parentNode) { | |
#Node is missing so let's get the parent. | |
$parentNode = $document.SelectSingleNode("//$($transformNode.ParentNode.LocalName)") | |
} | |
if(!$parentNode) { | |
Write-Host "- [InsertAfter] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName) skipped" -ForegroundColor Yellow | |
continue | |
} | |
$path = $transformType.Value.Replace("InsertAfter(","").Replace(")","") | |
$afterNode = $document.SelectSingleNode($path) | |
$newNode = $document.ImportNode($transformNode, $true) | |
$transformNode.Attributes | ForEach-Object { | |
if ($_.Name -like "xdt:*") { | |
$newNode.RemoveAttribute($_.Name) > $null | |
} | |
} | |
if ($afterNode) { | |
Write-Host "- [InsertAfter] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName) after $($afterNode.LocalName)" -ForegroundColor Blue | |
$parentNode.InsertAfter($newNode, $afterNode) > $null | |
} else { | |
Write-Host "- [InsertAfter] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName)" -ForegroundColor Blue | |
$parentNode.AppendChild($newNode) > $null | |
} | |
} | |
"Remove" { | |
if(!$nodeToModify) { | |
Write-Host "- [Remove] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName) skipped" -ForegroundColor Yellow | |
continue | |
} | |
$parentNode = $nodeToModify.ParentNode | |
Write-Host "- [Remove] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName)" -ForegroundColor Blue | |
$parentNode.RemoveChild($nodeToModify) > $null | |
} | |
"RemoveAll" { | |
# TODO: Should RemoveAll consider the element type? | |
$parentNode = $nodeToModify.ParentNode | |
if(!$parentNode) { | |
Write-Host "- [RemoveAll] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName) skipped" -ForegroundColor Yellow | |
continue | |
} | |
Write-Host "- [RemoveAll] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName)" -ForegroundColor Blue | |
if($transformNode.Attributes["xdt:Locator"]) { | |
$parentNode.RemoveChild($nodeToModify) > $null | |
} else { | |
$matchingNodes = $parentNode.SelectNodes("$($transformNode.LocalName)") | |
$matchingNodes | ForEach-Object { $parentNode.RemoveChild($_) > $null } | |
#$parentNode.RemoveAll() > $null | |
} | |
} | |
"RemoveAttributes*" { | |
if(!$nodeToModify) { | |
Write-Host "- [RemoveAttributes] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName) skipped" -ForegroundColor Yellow | |
continue | |
} | |
Write-Host "- [RemoveAttributes] $($transformNode.ParentNode.LocalName)/$($transformNode.LocalName)" -ForegroundColor Blue | |
$attributesToRemove = $transformType.Value.Replace("RemoveAttributes","").Replace("(","").Replace(")","").Split(",") | |
if(!$attributesToRemove) { | |
$nodesToModify.Attributes.RemoveAll() > $null | |
} else { | |
@($attributesToRemove) | ForEach-Object { | |
$nodeToModify.Attributes.Remove($nodeToModify.Attributes[$_]) > $null | |
} | |
} | |
} | |
} | |
} | |
} | |
} catch { | |
Write-Error "Error applying XDT transform: $_" | |
return $Base | |
} | |
return $document | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
. .\Merge-XdtTransform.ps1 | |
$XdtDllPath = ".\Microsoft.Web.XmlTransform.dll" | |
Add-Type -Path $XdtDllPath | |
function Invoke-XdtTransform { | |
param( | |
[string]$Base, | |
[string]$Transform, | |
[ref]$Output | |
) | |
$stringReader = New-Object System.IO.StringReader($Base) | |
$xmlReader = [System.Xml.XmlReader]::Create($stringReader) | |
$target = New-Object Microsoft.Web.XmlTransform.XmlTransformableDocument | |
$target.PreserveWhitespace = $true | |
$target.Load($xmlReader) | |
$transformation = New-Object Microsoft.Web.XmlTransform.XmlTransformation($Transform, $false, $null); | |
if (!$transformation.Apply($target)) | |
{ | |
return $Base | |
} | |
$stringWriter = New-Object System.IO.StringWriter | |
$xmlWriter = New-Object System.XMl.XmlTextWriter $stringWriter | |
$target.WriteContentTo($xmlWriter) | |
$xmlWriter.Flush() | |
$stringWriter.Flush() | |
return [xml]($stringWriter.ToString()) | |
} | |
[xml]$xmlBase = @" | |
<?xml version="1.0" encoding="utf-8"?> | |
<!-- | |
For more information on how to configure your ASP.NET application, please visit | |
https://go.microsoft.com/fwlink/?LinkId=169433 | |
--> | |
<configuration> | |
<configSections> | |
<section name="sitecore" type="Sitecore.Configuration.RuleBasedConfigReader, Sitecore.Kernel" /> | |
</configSections> | |
<connectionStrings> | |
<add name="WebContext" connectionString="" providerName="System.Data.SqlClient" /> | |
<add name="PaymentsContext" connectionString="" providerName="System.Data.SqlClient" /> | |
</connectionStrings> | |
<appSettings file="Base.config"> | |
<add key="Environment" value="" /> | |
<add key="IsTestMode" value="true" /> | |
<add key="IsStaging" value="true" /> | |
<add key="IsDisabled" value="true" /> | |
</appSettings> | |
<rewrite> | |
<rules> | |
<rule /> | |
<rule /> | |
</rules> | |
</rewrite> | |
<system.web> | |
<compilation defaultLanguage="c#" debug="false" targetFramework="4.8" /> | |
<membership defaultProvider="sitecore" hashAlgorithmType="SHA1"> | |
</membership> | |
<compilation> | |
<assemblies> | |
</assemblies> | |
</compilation> | |
<application coldstart="true" user="root" /> | |
</system.web> | |
<system.webServer> | |
<urlCompression doDynamicCompression="true" /> | |
<httpCookies httpOnlyCookies="true" requireSSL="false" /> | |
</system.webServer> | |
</configuration> | |
"@ | |
[xml]$xmlTransform = @" | |
<?xml version="1.0" encoding="utf-8"?> | |
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> | |
<configSections> | |
<section xdt:Transform="Replace" xdt:Locator="Match(name)" name="sitecore" type="Scms.Foundation.Configuration.EnvironmentVariablesConfigReader, Scms.Foundation"/> | |
</configSections> | |
<connectionStrings> | |
<add xdt:Transform="SetAttributes" xdt:Locator="Match(name)" name="WebContext" connectionString="data source=CHS-CADEVDB01;initial catalog=Web;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" /> | |
<add xdt:Transform="Replace" xdt:Locator="XPath(configuration/connectionStrings/add[@name='PaymentsContext'])" name="PaymentsContext" connectionString="data source=CHS-CADEVDB01;initial catalog=Payments;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" /> | |
</connectionStrings> | |
<appSettings> | |
<add xdt:Transform="SetAttributes" xdt:Locator="Match(key)" key="Environment" value="Development" /> | |
<add xdt:Transform="CommentOut" xdt:Locator="Match(key)" key="IsTestMode" /> | |
<add xdt:Locator="Condition(@key='IsStaging' or @key='IsDisabled')" xdt:Transform="Remove"/> | |
</appSettings > | |
<rewrite> | |
<rules> | |
<rule xdt:Transform="RemoveAll" /> | |
</rules> | |
</rewrite> | |
<system.web> | |
<machineKey xdt:Transform="Remove" /> | |
<machineKey xdt:Transform="InsertBefore(/configuration/system.web/membership)" validationKey="42F21E06B91BC207DAFFF53FDD44375515938CCEF1BF7F2CA70052B3B024C009B385A6E86D816ED1B0144D7BDEAEEECD9C14B20BBD02A29B1C0B1683493497D6" decryptionKey="DF97132E23EE6B974E7EC9FA3701B71BC4EBA440F1A56C744179529786C6EE58" validation="SHA1" decryption="AES" /> | |
<compilation> | |
<assemblies xdt:Locator="Condition(count(*) = 0)" xdt:Transform="Remove"/> | |
</compilation> | |
<application coldstart="true" user="root" xdt:Transform="Remove" /> | |
<compilation xdt:Locator="Condition(count(*) = 0)" xdt:Transform="Remove" /> | |
<application xdt:Transform="Replace" user="guest" type="web" /> | |
</system.web> | |
<location xdt:Transform="InsertAfter(/configuration/system.webServer)" path="sitecore"> | |
<system.web> | |
<authorization> | |
<deny users="*"/> | |
</authorization> | |
</system.web> | |
</location> | |
<system.webServer> | |
<urlCompression xdt:Transform="Insert" doDynamicCompression="true" /> | |
<httpCookies xdt:Transform="InsertIfMissing" httpOnlyCookies="true" requireSSL="true" /> | |
</system.webServer> | |
<compilation xdt:Transform="RemoveAttributes(debug)" /> | |
</configuration> | |
"@ | |
function Format-Xml ([xml]$xml, $indent=2) { | |
$StringWriter = New-Object System.IO.StringWriter | |
$XmlWriter = New-Object System.XMl.XmlTextWriter $StringWriter | |
$xmlWriter.Formatting = "indented" | |
$xmlWriter.Indentation = $Indent | |
$xml.WriteContentTo($XmlWriter) | |
$XmlWriter.Flush() | |
$StringWriter.Flush() | |
Write-Output $StringWriter.ToString() | |
} | |
#if(Merge-XdtTransform -Base $xmlBase -Transform $xmlTransform) { | |
# Format-Xml -Xml $xmlBase | |
#} | |
function Assert-AreEqual { | |
param( | |
[string]$TestName, | |
[object]$Expected, | |
[object]$Actual | |
) | |
$sb = New-Object System.Text.StringBuilder | |
if ($Expected -ne $Actual) { | |
$sb.AppendLine("[$($TestName)] Failed") > $null | |
$sb.AppendLine("Expected") > $null | |
$sb.AppendLine((Format-Xml -Xml $Expected)) > $null | |
$sb.AppendLine("Actual") > $null | |
$sb.AppendLine((Format-Xml -Xml $Actual)) > $null | |
Write-Host $sb.ToString() -ForegroundColor Red -BackgroundColor White | |
return $false | |
} else { | |
$sb.AppendLine("[$($TestName)] Succeeded") > $null | |
Write-Host $sb.ToString() -ForegroundColor Green | |
} | |
return $true | |
} | |
[xml]$replaceTestBaseXml = @" | |
<?xml version="1.0"?> | |
<configuration> | |
<system.web> | |
<compilation debug="true" strict="true" batch="true" /> | |
<application coldstart="true" user="root"> | |
<subtag>old content</subtag> | |
<subtag2>old content</subtag2> | |
</application> | |
</system.web> | |
</configuration> | |
"@ | |
[xml]$replaceTestTransformXml = @" | |
<?xml version="1.0"?> | |
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> | |
<system.web> | |
<!-- Replaces the whole tag --> | |
<application xdt:Transform="Replace" user="guest" type="web" > | |
<sub>new content</sub> | |
</application> | |
</system.web> | |
</configuration> | |
"@ | |
$testExpectedXml = Invoke-XdtTransform -Base $replaceTestBaseXml.OuterXml -Transform $replaceTestTransformXml.OuterXml | |
$testActualXml = Merge-XdtTransform -Base $replaceTestBaseXml -Transform $replaceTestTransformXml | |
Assert-AreEqual -TestName "Test_Replace" -Expected $testExpectedXml.OuterXml -Actual $testActualXml.OuterXml > $null | |
[xml]$removeTestBaseXml = @" | |
<?xml version="1.0"?> | |
<configuration> | |
<appSettings> | |
<add key="IsStaging" value="True" /> | |
<add key="Environment" value="Dev" /> | |
<add key="Version" value="14" /> | |
</appSettings> | |
</configuration> | |
"@ | |
[xml]$removeTestTransformXml = @" | |
<?xml version="1.0"?> | |
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> | |
<appSettings> | |
<add key="Environment" | |
xdt:Locator="Match(key)" xdt:Transform="Remove" /> | |
</appSettings> | |
</configuration> | |
"@ | |
$testExpectedXml = Invoke-XdtTransform -Base $removeTestBaseXml.Clone().OuterXml -Transform $removeTestTransformXml.OuterXml | |
$testActualXml = Merge-XdtTransform -Base $removeTestBaseXml -Transform $removeTestTransformXml | |
Assert-AreEqual -TestName "Test_Remove" -Expected $testExpectedXml.OuterXml -Actual $testActualXml.OuterXml > $null | |
[xml]$removeAllTestBaseXml = @" | |
<?xml version="1.0"?> | |
<configuration> | |
<appSettings> | |
<add key="IsStaging" value="True" /> | |
<add key="Environment" value="Dev" /> | |
<add key="Version" value="14" /> | |
<object key="" /> | |
</appSettings> | |
</configuration> | |
"@ | |
[xml]$removeAllTestTransformXml = @" | |
<?xml version="1.0"?> | |
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> | |
<appSettings> | |
<add xdt:Transform="RemoveAll" /> | |
</appSettings> | |
</configuration> | |
"@ | |
$testExpectedXml = Invoke-XdtTransform -Base $removeAllTestBaseXml.OuterXml -Transform $removeAllTestTransformXml.OuterXml | |
$testActualXml = Merge-XdtTransform -Base $removeAllTestBaseXml -Transform $removeAllTestTransformXml | |
Assert-AreEqual -TestName "Test_RemoveAll" -Expected $testExpectedXml.OuterXml -Actual $testActualXml.OuterXml > $null | |
[xml]$removeAllMatchTestBaseXml = @" | |
<?xml version="1.0"?> | |
<configuration> | |
<appSettings> | |
<add key="IsStaging" value="True" /> | |
<add key="Environment" value="Dev" /> | |
<add key="SiteStyle" value="dark" /> | |
<add key="Environment" value="Prod" /> | |
<add key="Version" value="14" /> | |
<add key="Environment" value="Staging" /> | |
</appSettings> | |
</configuration> | |
"@ | |
[xml]$removeAllMatchTestTransformXml = @" | |
<?xml version="1.0"?> | |
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> | |
<appSettings> | |
<add key="Environment" | |
xdt:Locator="Match(key)" xdt:Transform="RemoveAll"/> | |
</appSettings> | |
</configuration> | |
"@ | |
$testExpectedXml = Invoke-XdtTransform -Base $removeAllMatchTestBaseXml.OuterXml -Transform $removeAllMatchTestTransformXml.OuterXml | |
$testActualXml = Merge-XdtTransform -Base $removeAllMatchTestBaseXml -Transform $removeAllMatchTestTransformXml | |
Assert-AreEqual -TestName "Test_RemoveAll_Match" -Expected $testExpectedXml.OuterXml -Actual $testActualXml.OuterXml > $null | |
[xml]$insertTestBaseXml = @" | |
<?xml version="1.0"?> | |
<configuration> | |
<appSettings> | |
<add key="IsStaging" value="True" /> | |
<add key="Environment" value="Dev" /> | |
</appSettings> | |
</configuration> | |
"@ | |
[xml]$insertTestTransformXml = @" | |
<?xml version="1.0"?> | |
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> | |
<appSettings> | |
<add key="SiteStyle" value="dark" | |
xdt:Locator="Match(key)" xdt:Transform="Insert" /> | |
</appSettings> | |
</configuration> | |
"@ | |
$testExpectedXml = Invoke-XdtTransform -Base $insertTestBaseXml.OuterXml -Transform $insertTestTransformXml.OuterXml | |
$testActualXml = Merge-XdtTransform -Base $insertTestBaseXml -Transform $insertTestTransformXml | |
Assert-AreEqual -TestName "Test_Insert" -Expected $testExpectedXml.OuterXml -Actual $testActualXml.OuterXml > $null | |
[xml]$insertIfMissingTestBaseXml = @" | |
<?xml version="1.0"?> | |
<configuration> | |
<appSettings> | |
<add key="IsStaging" value="True" /> | |
<add key="Environment" value="Dev" /> | |
</appSettings> | |
</configuration> | |
"@ | |
[xml]$insertIfMissingTestTransformXml = @" | |
<?xml version="1.0"?> | |
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> | |
<appSettings> | |
<!-- Will not be inserted since already existing in the source--> | |
<add key="Environment" value="Prod" | |
xdt:Locator="Match(key)" xdt:Transform="InsertIfMissing" /> | |
<add key="SiteStyle" value="Dark" | |
xdt:Locator="Match(key)" xdt:Transform="InsertIfMissing" /> | |
</appSettings> | |
</configuration> | |
"@ | |
$testExpectedXml = Invoke-XdtTransform -Base $insertIfMissingTestBaseXml.OuterXml -Transform $insertIfMissingTestTransformXml.OuterXml | |
$testActualXml = Merge-XdtTransform -Base $insertIfMissingTestBaseXml -Transform $insertIfMissingTestTransformXml | |
Assert-AreEqual -TestName "Test_InsertIfMissing" -Expected $testExpectedXml.OuterXml -Actual $testActualXml.OuterXml > $null | |
[xml]$insertBeforeTestBaseXml = @" | |
<?xml version="1.0"?> | |
<configuration> | |
<appSettings> | |
<add key="IsStaging" value="True" /> | |
<add key="Environment" value="Dev" /> | |
<add key="Version" value="14" /> | |
</appSettings> | |
</configuration> | |
"@ | |
[xml]$insertBeforeTestTransformXml = @" | |
<?xml version="1.0"?> | |
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> | |
<appSettings> | |
<add key="SiteStyle" value="dark" | |
xdt:Transform="InsertBefore(/configuration/appSettings/add[@key='Environment'])"/> | |
</appSettings> | |
</configuration> | |
"@ | |
$testExpectedXml = Invoke-XdtTransform -Base $insertBeforeTestBaseXml.OuterXml -Transform $insertBeforeTestTransformXml.OuterXml | |
$testActualXml = Merge-XdtTransform -Base $insertBeforeTestBaseXml -Transform $insertBeforeTestTransformXml | |
Assert-AreEqual -TestName "Test_InsertBefore" -Expected $testExpectedXml.OuterXml -Actual $testActualXml.OuterXml > $null | |
[xml]$insertAfterTestBaseXml = @" | |
<?xml version="1.0"?> | |
<configuration> | |
<appSettings> | |
<add key="IsStaging" value="True" /> | |
<add key="Environment" value="Dev" /> | |
<add key="Version" value="14" /> | |
</appSettings> | |
</configuration> | |
"@ | |
[xml]$insertAfterTestTransformXml = @" | |
<?xml version="1.0"?> | |
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> | |
<appSettings> | |
<add key="SiteStyle" value="dark" | |
xdt:Transform="InsertAfter(/configuration/appSettings/add[@key='Environment'])"/> | |
</appSettings> | |
</configuration> | |
"@ | |
$testExpectedXml = Invoke-XdtTransform -Base $insertAfterTestBaseXml.OuterXml -Transform $insertAfterTestTransformXml.OuterXml | |
$testActualXml = Merge-XdtTransform -Base $insertAfterTestBaseXml -Transform $insertAfterTestTransformXml | |
Assert-AreEqual -TestName "Test_InsertAfter" -Expected $testExpectedXml.OuterXml -Actual $testActualXml.OuterXml > $null | |
[xml]$commentOutTestBaseXml = @" | |
<?xml version="1.0"?> | |
<configuration> | |
<appSettings> | |
<add key="IsStaging" value="True" /> | |
<add key="Environment" value="Dev" /> | |
<add key="Version" value="14" /> | |
</appSettings> | |
</configuration> | |
"@ | |
[xml]$commentOutTestTransformXml = @" | |
<?xml version="1.0"?> | |
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> | |
<appSettings> | |
<add key="Environment" | |
xdt:Locator="Match(key)" xdt:Transform="CommentOut" /> | |
</appSettings> | |
</configuration> | |
"@ | |
$testExpectedXml = Invoke-XdtTransform -Base $commentOutTestBaseXml.OuterXml -Transform $commentOutTestTransformXml.OuterXml | |
$testActualXml = Merge-XdtTransform -Base $commentOutTestBaseXml -Transform $commentOutTestTransformXml | |
Assert-AreEqual -TestName "Test_CommentOut" -Expected $testExpectedXml.OuterXml -Actual $testActualXml.OuterXml > $null | |
[xml]$removeAttributesTestBaseXml = @" | |
<?xml version="1.0"?> | |
<configuration> | |
<system.web> | |
<application coldstart="true" user="root" /> | |
<compilation debug="true" strict="true" batch="true" /> | |
</system.web> | |
</configuration> | |
"@ | |
[xml]$removeAttributesTestTransformXml = @" | |
<?xml version="1.0"?> | |
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> | |
<system.web> | |
<!-- Remove all attributes--> | |
<application xdt:Transform="RemoveAttributes" /> | |
<!-- Remove specific attributes--> | |
<compilation xdt:Transform="RemoveAttributes(debug,strict)" /> | |
</system.web> | |
</configuration> | |
"@ | |
$testExpectedXml = Invoke-XdtTransform -Base $removeAttributesTestBaseXml.OuterXml -Transform $removeAttributesTestTransformXml.OuterXml | |
$testActualXml = Merge-XdtTransform -Base $removeAttributesTestBaseXml -Transform $removeAttributesTestTransformXml | |
Assert-AreEqual -TestName "Test_RemoveAttributes" -Expected $testExpectedXml.OuterXml -Actual $testActualXml.OuterXml > $null | |
[xml]$setAttributesTestBaseXml = @" | |
<?xml version="1.0"?> | |
<configuration> | |
<system.web> | |
<application coldstart="true" user="root" /> | |
<compilation debug="true" strict="true" batch="true" /> | |
</system.web> | |
</configuration> | |
"@ | |
[xml]$setAttributesTestTransformXml = @" | |
<?xml version="1.0"?> | |
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> | |
<system.web> | |
<!-- Add or updates all attributes--> | |
<application user="guest" newAttribute="value" | |
xdt:Transform="SetAttributes" /> | |
<!-- Add or updates specific attributes--> | |
<compilation debug="false" strict="false" batch="false" | |
xdt:Transform="SetAttributes(debug,strict)" /> | |
</system.web> | |
</configuration> | |
"@ | |
$testExpectedXml = Invoke-XdtTransform -Base $setAttributesTestBaseXml.OuterXml -Transform $setAttributesTestTransformXml.OuterXml | |
$testActualXml = Merge-XdtTransform -Base $setAttributesTestBaseXml -Transform $setAttributesTestTransformXml | |
Assert-AreEqual -TestName "SetAttributes_Element" -Expected $testExpectedXml.OuterXml -Actual $testActualXml.OuterXml > $null | |
[xml]$setAttributesMatchTestBaseXml = @" | |
<?xml version="1.0"?> | |
<configuration> | |
<appSettings> | |
<add key="IsStaging" value="True" /> | |
<add key="Environment" value="Dev" /> | |
<add key="SiteStyle" value="dark" /> | |
</appSettings> | |
</configuration> | |
"@ | |
[xml]$setAttributesMatchTestTransformXml = @" | |
<?xml version="1.0"?> | |
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> | |
<appSettings> | |
<add key="Environment" value="Prod" | |
xdt:Locator="Match(key)" xdt:Transform="SetAttributes"/> | |
</appSettings> | |
</configuration> | |
"@ | |
$testExpectedXml = Invoke-XdtTransform -Base $setAttributesMatchTestBaseXml.OuterXml -Transform $setAttributesMatchTestTransformXml.OuterXml | |
$testActualXml = Merge-XdtTransform -Base $setAttributesMatchTestBaseXml -Transform $setAttributesMatchTestTransformXml | |
Assert-AreEqual -TestName "Test_SetAttributesMatch" -Expected $testExpectedXml.OuterXml -Actual $testActualXml.OuterXml > $null | |
# TODO: Add tests for Condition and XPath |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Found this neat website to perform transforms in the browser. Convenient to compare with results of this script.
Xdt Playground