The following is an overview on how to inject a new XML tag into an XML file at a specific location using a Powershell script. The functionality is often used during automated deployment but has several uses. There are several methods for accomplishing this, however I found the following to be most compatible with several versions.
Function AddClientToXml
{
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
$configFilePath
)
# Load the web.config file into an XML document.
$xmlDoc = New-Object System.Xml.XmlDocument
$xmlDoc.Load($configFilePath)
# Create our XML to be inserted
$clientXml = @"
<client>
<endpoint address="RegistrationAddressValue"
behaviorConfiguration="SampleClientCertificateBehavior" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_RegistrationService"
contract="Registration.RegistrationService" name="WSHttpBinding_RegistrationService">
<identity>
<dns value="RegistrationDNS" />
</identity>
</endpoint>
</client>
"@
$clientNodes = $xmlDoc.SelectSingleNode("//system.serviceModel/client")
# Check to see if the <client> node already exists.
if ($clientNodes.Count -gt 0) {
# The <client> node exists, so we'll replace it with the new one.
# Set $clientNode to it's first child node.
$clientNode = $clientNodes[0]
# Replace the <client> node with $clientXML element
$clientNode.ParentNode.ReplaceChild($xmlDoc.ImportNode($clientXml.DocumentElement, $true), $clientNode)
}
else
{
# The <client> node doesn't exist, so we'll create it.
$serviceModelNode = $xmlDoc.SelectSingleNode('//system.serviceModel')
# Load the $clientXml string into a new XmlDocument object.
$newXmlDoc = New-Object System.Xml.XmlDocument
$newXmlDoc.LoadXml($clientXml)
# Get the $clientXml as a node
$importedNode = $xmlDoc.ImportNode($newXmlDoc.DocumentElement, $true)
# Append the $importedNode to the $serviceModelNode
$serviceModelNode.AppendChild($importedNode)
$xmlDoc.Save($configFilePath)
}
return $xmlDoc
}
$webConfigPath = "C:\PATH TO WEB.CONFIG\Web.config"
AddClientToXml($webConfigPath)
After running the script the web.config specified to the function should resemble the following:
<system.serviceModel>
<bindings>
...
</bindings>
<client>
<endpoint address="RegistrationAddressValue"
behaviorConfiguration="SampleClientCertificateBehavior" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_RegistrationService"
contract="Registration.RegistrationService" name="WSHttpBinding_RegistrationService">
<identity>
<dns value="RegistrationDNS" />
</identity>
</endpoint>
</client>
<behaviors>
...
</behaviors>
</system.serviceModel>
This approach is particularly useful when using CI/CD to deploy your code base to environments that require different configurations.
Hope this helps!