XmlContentDsc.psm1
enum Ensure { Absent Present } [DscResource()] class XmlFileContentResource { [DscProperty(Key)] [string]$Path [DscProperty(Key)] [string]$XPath [DscProperty()] [hashtable]$Attributes [DscProperty(Mandatory)] [Ensure]$Ensure [void] Set() { $xml = [xml](Get-Content -Path $this.Path) if ($this.Ensure -eq 'Present') { $element = $xml | Select-Xml -XPath $this.XPath | Select-Object -ExpandProperty Node $parentXPath = $this.XPath.Substring(0, $this.XPath.LastIndexOf('/')) $parent = $xml | Select-Xml -XPath $parentXPath if (-not $element) { $newElementName = $this.XPath.Substring($this.XPath.LastIndexOf('/') + 1) $element = $parent.Node.OwnerDocument.CreateElement($newElementName) $parent.Node.AppendChild($element) } if ($this.Attributes) { foreach ($kvp in $this.Attributes.GetEnumerator()) { $attribute = $element.Attributes | Where-Object Name -eq $kvp.Name if ($attribute) { if ($attribute.Value -eq $kvp.Value) { continue } else { $attribute.Value = $kvp.Value } } else { $attribute = $parent.Node.OwnerDocument.CreateAttribute($kvp.Name) $attribute.Value = $kvp.Value $element.Attributes.Append($attribute) } } $attributesCollection = New-Object System.Xml.XmlAttribute[]($element.Attributes.Count) $element.Attributes.CopyTo($attributesCollection, 0) foreach ($attribute in $attributesCollection) { if (-not $this.Attributes.ContainsKey($attribute.Name)) { $element.Attributes.RemoveNamedItem($attribute.Name) } } } } else { $element = $xml | Select-Xml -XPath $this.XPath if ($element) { $element.Node.ParentNode.RemoveChild($element.Node) } } $xml.Save($this.Path) } [bool] Test() { $currentState = $this.Get() $attributesEqual = if ($this.Attributes) { Compare-Hashtable -Hashtable1 $this.Attributes -Hashtable2 $currentState.Attributes } else { $true } return ($this.Ensure -eq $currentState.Ensure) -band $attributesEqual } [XmlFileContentResource]Get() { $currentState = New-Object XmlFileContentResource $currentState.Path = $this.Path $currentState.XPath = $this.XPath $currentState.Attributes = @{} $xml = [xml](Get-Content -Path $this.Path) $node = $xml | Select-Xml -XPath $this.XPath | Select-Object -ExpandProperty Node if ($node) { $currentState.Ensure = 'Present' } else { $currentState.Ensure = 'Absent' } foreach ($attribute in $node.Attributes) { $currentState.Attributes.Add($attribute.Name, $attribute.Value) } return $currentState } } function Compare-Hashtable { param( [Parameter(Mandatory)] [hashtable]$Hashtable1, [Parameter(Mandatory)] [hashtable]$Hashtable2 ) foreach ($kvp in $Hashtable1.GetEnumerator()) { if (-not $Hashtable2.ContainsKey($kvp.Name)) { return $false } if ($Hashtable1[$kvp.Name] -ne $Hashtable2[$kvp.Name]) { return $false } } foreach ($kvp in $Hashtable2.GetEnumerator()) { if (-not $Hashtable1.ContainsKey($kvp.Name)) { return $false } if ($Hashtable2[$kvp.Name] -ne $Hashtable1[$kvp.Name]) { return $false } } return $true } #$x = New-Object XmlFileContentResource #$x.Path = 'D:\web.config' #$x.Ensure = 'Present' #$x.XPath = '/configuration/appSettings/Test1' #$x.Attributes = @{ TestValue2 = '123'; Name = 'Hans' } # #if (-not $x.Test()) #{ # Write-Host 'invoking set' # $x.Set() #} |