xml-utils.ps1

#
# xml_utils.ps1
#
function New-IISHandler
{
    <#
        .SYNOPSIS
            Adds a new entry to the web.config handlers section
 
        .EXAMPLE
            This sample command:
     
                New-IISHandler -XmlPath 'C:\web.config' -Name "CaptchaAudio" -Path 'CaptchaAudio.axd' -Type "Sitecore.Form.Core.Pipeline.RequestProcessor.CaptchaResolver, Sitecore.Forms.Core" -Verb "*"
     
            Will add this element in web.config file:
                <add name="CaptchaAudio" path="CaptchaAudio.axd" type="Sitecore.Form.Core.Pipeline.RequestProcessor.CaptchaResolver, Sitecore.Forms.Core" verb="*" />
         
        .LINK
            https://www.iis.net/configreference/system.webserver/handlers
        .LINK
            This is part of Sitecore-Automation module https://www.powershellgallery.com/packages/sitecore-automation
    #>

    [CmdletBinding(SupportsShouldProcess=$true)]
    Param(
        [Parameter(Mandatory=$true)]
        [ValidateScript ({Test-Path $_})]
        [string]$XmlPath,
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,
        [Parameter(Mandatory=$true)]
        [string]$Path,
        [Parameter(Mandatory=$true)]
        [string]$Type,
        [Parameter(Mandatory=$true)]
        [string]$Verb,

        [string]$Comment,
        
        [bool]$Backup
    )

    [xml]$XmlDocument = Get-Content -Path $XmlPath

    $handlers = $XmlDocument.SelectSingleNode("//configuration/system.webServer/handlers")
    if($handlers -eq $null)
    {
        $(throw "IIS Handlers does not Exists! Invalid Configuration File.")
    }

    $handler = $handlers.ChildNodes | Where-Object {$_ -ne $null -and $_.Name -eq $Name}

    if( $handler -eq $null )
    {
        $item = $XmlDocument.CreateElement("add")
        
        $item.SetAttribute("name",  $Name)
        $item.SetAttribute("path",  $Path)
        $item.SetAttribute("type",  $Type)
        $item.SetAttribute("verb",  $Verb)

        if( [String]::IsNullOrWhiteSpace($Comment) -eq $false )
        {
            $xmlComment = $XmlDocument.CreateComment($Comment);
            $handlers.AppendChild($xmlComment)
        }
        
        $handlers.AppendChild($item)

        if ($pscmdlet.ShouldProcess($XmlPath))
        {
            if( $Backup -eq $true)
            {
                Backup-File -SourceFile $XmlPath
            }

            $XmlDocument.Save($XmlPath);
        }
    }
    else
    {
        Write-Verbose "A handler with a name '$Name' already exist."
    }
}


function Remove-IISHandler
{
    [CmdletBinding(SupportsShouldProcess=$true)]
    Param(
        [Parameter(Mandatory=$true)]
        [ValidateScript ({Test-Path $_})]
        [string]$XmlPath,
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$Name
        )

    [xml]$XmlDocument = Get-Content -Path $XmlPath

    $handlers = $XmlDocument.SelectSingleNode("//configuration/system.webServer/handlers")
    if($handlers -eq $null)
    {
        $(throw "IIS Handlers does not Exists! Invalid Configuration File.")
    }
    $handler = $handlers.ChildNodes | Where-Object {$_ -ne $null -and $_.Name -eq $Name}

    if( $handler -ne $null )
    {
        Write-Verbose $handler.OuterXml
    
        if ($pscmdlet.ShouldProcess($XmlPath))
        {
            if( $Backup -eq $true)
            {
                Backup-File -SourceFile $XmlPath
            }

            $handlers.RemoveChild($handler)
            $XmlDocument.Save($XmlPath);
        }
    }
}


function Disable-IISHandler
{
    [CmdletBinding(SupportsShouldProcess=$true)]
    Param(
        [Parameter(Mandatory=$true)]
        [ValidateScript ({Test-Path $_})]
        [string]$XmlPath,
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$Name
        )

    [xml]$XmlDocument = Get-Content -Path $XmlPath

    $handlers = $XmlDocument.SelectSingleNode("//configuration/system.webServer/handlers")
    if($handlers -eq $null)
    {
        $(throw "IIS Handlers does not Exists! Invalid Configuration File.")
    }

    $handler = $handlers.ChildNodes | Where-Object {$_ -ne $null -and $_.Name -eq $Name}

    if( $handler -ne $null )
    {
        Write-Verbose $handler.OuterXml
    
        if ($pscmdlet.ShouldProcess($XmlPath))
        {
            if( $Backup -eq $true)
            {
                Backup-File -SourceFile $XmlPath
            }

            $xmlComment = $XmlDocument.CreateComment($handler.OuterXml);

            $handlers.InsertBefore($xmlComment, $handler)
            $handlers.RemoveChild($handler)

            $XmlDocument.Save($XmlPath);
        }
    }
}


function New-SettingsFile
{
    [CmdletBinding(SupportsShouldProcess=$true)]
    Param(
        [Parameter(Mandatory=$true)]
        [string]$XmlPath,
        [string]$Comment
        )
    
    [System.XML.XMLDocument]$XmlDocument = New-Object System.XML.XMLDocument


    #$configuration = $XmlDocument.CreateElement("patch","configuration","http://www.sitecore.net/xmlconfig/")
    $configuration = $XmlDocument.CreateElement("configuration")
    $configuration.SetAttribute("xmlns:patch",  "http://www.sitecore.net/xmlconfig/")

    $sitecore = $XmlDocument.CreateElement("sitecore")
    $settings = $XmlDocument.CreateElement("settings")

    $XmlDocument.appendChild($configuration)
    $configuration.appendChild($sitecore)
    $sitecore.appendChild($settings)

    
    if( [String]::IsNullOrWhiteSpace($Comment) -eq $false )
    {
        $xmlComment = $XmlDocument.CreateComment($Comment);
        $XmlDocument.InsertBefore($xmlComment,$configuration)
    }

    $XmlDocument.Save($XmlPath);
}


function New-SettingsPatch
{
    [CmdletBinding(SupportsShouldProcess=$true)]
    Param(
        [Parameter(Mandatory=$true)]
        [ValidateScript ({Test-Path $_})]
        [string]$XmlPath,

        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$Value,
        
        [string]$Comment,

        [bool]$Backup
    )

    [xml]$XmlDocument = Get-Content -Path $XmlPath

    $sitecoreSettings = "//configuration/sitecore/settings"
 
    $appSettingsNode = $XmlDocument.SelectSingleNode($sitecoreSettings)
 
    if($appSettingsNode -eq $null)
    {
        $(throw "Sitecore Settings Does not Exists! Invalid Configuration File.")
    }

    $existingNode = $XmlDocument.SelectNodes("//configuration/sitecore/settings/setting") | Where-Object {$_ -ne $null -and $_.Name -eq $Name}
    if( $existingNode -ne $null )
    {
        Write-Verbose "Patch for setting $Name already exist"
        return
    }

    [XmlElement]$item = $XmlDocument.CreateElement("setting")
    $item.SetAttribute("name",  $Name)

    $patch = $XmlDocument.CreateElement("patch","attribute","http://www.sitecore.net/xmlconfig/")
    $patch.SetAttribute("name",  "value")
    $patch.InnerText = $Value
    $item.AppendChild($patch)

    $appSettingsNode.AppendChild($item);
    
    if( [String]::IsNullOrWhiteSpace($Comment) -eq $false )
    {
        $xmlComment = $XmlDocument.CreateComment($Comment);
        $appSettingsNode.InsertBefore($xmlComment,$item)
    }

    if ($pscmdlet.ShouldProcess($XmlPath))
    {
        if( $Backup -eq $true)
        {
            Backup-File -SourceFile $XmlPath
        }
        $XmlDocument.Save($XmlPath);
    }
}



function Test-XmlAttribute 
{
    <#
        .SYNOPSIS
            Checks if passed node has an attribute and an attribute has an expected value
 
        .EXAMPLE
            This sample command:
             
            [System.Xml.XmlNode]$node = $XmlDocument.SelectSingleNode("//compilation")
            Test-XmlAttribute -Node $node -AttrName 'optimizeCompilations' -ExpectedValue 'true'
             
            If compilation node looks like belowe, then Test-XmlAttribute returns true.
            <compilation defaultLanguage="c#" debug="false" targetFramework="4.5.2" optimizeCompilations="true">
        .LINK
            This is part of Sitecore-Automation module https://www.powershellgallery.com/packages/sitecore-automation
    #>

    [CmdletBinding(SupportsShouldProcess=$true)]
    Param(
    [System.Xml.XmlNode] $Node, 
    [string] $AttrName,
    [string] $ExpectedValue = $null
    )
    $attr = $Node.Attributes[$AttrName]
    if( $attr  -ne $null )
    {
        if( $ExpectedValue -ne $null -and $attr.Value -ne $ExpectedValue )
        {
            return $false
        }

        return $true
    }
    else
    {
        return $false
    }
    
}



function Set-XmlAttribute 
{
    <#
        .SYNOPSIS
            Sets an attribute value to expected value in the node passed as -Node parameter.
 
        .EXAMPLE
             
            [System.Xml.XmlNode]$node = $XmlDocument.SelectSingleNode("//compilation")
            Set-XmlAttribute -Node $compilation -AttrName 'debug' -ExpectedValue 'false'
             
            The 'compilation' node before run a command:
            <compilation defaultLanguage="c#" debug="true" targetFramework="4.5.2">
             
            The 'compilation' node after run a command (attribute debug has changed value):
            <compilation defaultLanguage="c#" debug="false" targetFramework="4.5.2">
             
        .EXAMPLE
             
            [System.Xml.XmlNode]$node = $XmlDocument.SelectSingleNode("//compilation")
            Set-XmlAttribute -Node $compilation -AttrName 'optimizeCompilations' -ExpectedValue 'true' -Verbose -Force
 
            The 'compilation' node before run a command:
            <compilation defaultLanguage="c#" debug="true" targetFramework="4.5.2">
             
            The 'compilation' node after run a command (A new attribute was added because of -Force parameter):
            <compilation defaultLanguage="c#" debug="false" targetFramework="4.5.2" optimizeCompilations="true >
 
 
        .LINK
            This is part of Sitecore-Automation module https://www.powershellgallery.com/packages/sitecore-automation
    #>

    [CmdletBinding(SupportsShouldProcess=$true)]
    Param(
    [System.Xml.XmlNode] $Node, 
    [string] $AttrName,
    [string] $ExpectedValue,
    [switch] $Force = $false
    )
    $attr = $Node.Attributes[$AttrName]
    if( $attr  -ne $null )
    {
        Write-Verbose  "Current value of attribute $AttrName = $($attr.Value)"

        if( $attr.Value -ne $ExpectedValue )
        {
            Write-Verbose  "Set $AttrName to $ExpectedValue"
            $attr.Value = $ExpectedValue
        }
    }
    else
    {
        Write-Warning "Attribute '$AttrName' not exist."
        if( $Force -eq $true)
        {
            Write-Verbose  "Add new attribute $AttrName with value $ExpectedValue"
            $Node.SetAttribute($AttrName,  $ExpectedValue)
        }
    }
    
}