Private/Convert-HashTableToXML.ps1
function Convert-HashTableToXML() { <# .SYNOPSIS COnverts one or more Powershell hashtables into a simple XML format. .DESCRIPTION Creates simpler and more human-readable output for a hashtable than Export-CliXML or ConvertTo-XML. This is useful for instance when storing attributes or configuration variables for output to other program or storage in an AD CustomAttribute. This command will create appropriate subnodes if you have nested hashtables. .NOTES Adapted from original script by Blindrood (https://gallery.technet.microsoft.com/scriptcenter/Export-Hashtable-to-xml-in-122fda31) .PARAMETER InputObject A Powershell hashtable that contains the name-value pairs you wish to convert to XML elements .PARAMETER Root Allows you to specify the root XML element definition. .PARAMETER OutPath Path to an output XML file, if desired. If not specified, outputs directly to the pipeline .EXAMPLE Create a Hashtable PS C:\> $Configuration = @{ 'Definitions' = @{ 'ConnectionString' = 'sql=srv01;port=223' 'MonitoringLevel' = 'MonitoringLevelValue' } 'Conventions' = @{ 'MyConvention' = 'This is my convention' 'Option' = 'Zip' 'ServerType' = 'sql' 'Actions' = @{ 'SpecificAction' = 'DoNothing' 'DefaultAction' = 'Destroy it All' } 'ExceptionAction' = 125 'Period' = New-TimeSpan -Seconds 20 } 'ServiceAccount' = @{ 'UserName' = 'mydomain.com\thisisme' 'Password' = '123o123' } 'GroupConfiguration' = @{ 'AdminsGroup' = 'mydomain.com\thisisAdminsGroup' 'UsersGroup' = 'mydomain.com\thisisUsersGroup' } } .EXAMPLE Export the $Configuration | Out-HashTableToXml -Root 'Configuration' -File $env:temp\test.xml ----------------- Test.XML Contents ----------------- <Configuration> <Conventions> <ExceptionAction>125</ExceptionAction> <ServerType>sql</ServerType> <Actions> <SpecificAction>DoNothing</SpecificAction> <DefaultAction>Destroy it All</DefaultAction> </Actions> <Period>00:00:20</Period> <Option>Zip</Option> <MyConvention>This is my convention</MyConvention> </Conventions> <GroupConfiguration> <UsersGroup>mydomain.com\thisisUsersGroup</UsersGroup> <AdminsGroup>mydomain.com\thisisAdminsGroup</AdminsGroup> </GroupConfiguration> <Definitions> <MonitoringLevel>MonitoringLevelValue</MonitoringLevel> <ConnectionString>sql=srv01;port=223</ConnectionString> </Definitions> <ServiceAccount> <Password>123o123</Password> <UserName>mydomain.com\thisisme</UserName> </ServiceAccount> </Configuration> #> Param( [Parameter(ValueFromPipeline = $true, Position = 0)] [System.Collections.Hashtable]$InputObject, [ValidateScript({Test-Path $_ -IsValid})] [System.String]$OutPath, [System.String]$Root="PSHashTable" ) Begin{ $ScriptBlock = { Param($Elem, $Root) if( $Elem.Value -is [System.Collections.Hashtable] ){ $RootNode = $Root.AppendChild($Doc.CreateNode([System.Xml.XmlNodeType]::Element,$Elem.Key,$Null)) $Elem.Value.GetEnumerator() | ForEach-Object { $Scriptblock.Invoke( @($_, $RootNode) ) } } else{ $Element = $Doc.CreateElement($Elem.Key) $Element.InnerText = if($Elem.Value -is [Array]) { $Elem.Value -join ',' } else{ $Elem.Value | Out-String } $Root.AppendChild($Element) | Out-Null } } } #Begin Process{ $Doc = [xml]"<$($Root)></$($Root)>" $InputObject.GetEnumerator() | ForEach-Object { $scriptblock.Invoke( @($_, $doc.DocumentElement) ) } #Output the formatted XML document if OutPath is specified, otherwise send to pipeline if ($OutPath) {$doc.save($OutPath)} else {$doc} } #Process } #Out-HashTableToXML |