function ConvertTo-Hashtable { <# .SYNOPSIS Used to convert an object into a hashtable .EXAMPLE $json | ConvertFrom-Json | ConvertTo-HashTable .EXAMPLE [xml]$someXmlVariable | ConvertTo-HashTable .PARAMETER InputObject This is the object to convert .PARAMETER Recursing This indicates that we are calling ourselves, so don't convert the intermediary objects to a PSCustomObject .LINK https://4sysops.com/archives/convert-json-to-a-powershell-hash-table/ #> [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [Parameter(ValueFromPipeline)] $InputObject, [switch]$Recursing ) # Return null if the input is null. This can happen when calling the function # recursively and a property is null if ($null -eq $InputObject) { return $null } # We don't mess with existing hashtables if ($InputObject -is [System.Collections.Hashtable]) { return $InputObject } $properties = [System.Collections.Hashtable]@{} # Let's get us some XML out of there heck yeah if ($InputObject -is [System.Xml.XmlNode]) { $properties = [System.Collections.Hashtable]@{} $element = $InputObject if ($element.HasAttributes) { $properties.Attributes = [System.Collections.Hashtable]@{} $attributes = $element.Attributes foreach ($attribute in $attributes) { $name = $attribute.Name if (![string]::IsNullOrWhiteSpace($attribute.Prefix)){ $name = $name.Replace("$($attribute.Prefix):","") } $properties.Attributes[$name] = $attribute.Value } } if (!$element.IsEmpty) { # This should handle "innerText only" nodes as well if ($element.HasChildNodes) { $nodes = $element.ChildNodes foreach ($node in $nodes) { #Write-Host $node $name = $node.Name if (![string]::IsNullOrWhiteSpace($node.Prefix)){ $name = $name.Replace("$($node.Prefix):","") } if ($name -eq '#text') { $properties["#text"] = $element.InnerText } else { $properties[$name] = (ConvertTo-Hashtable $node -Recursing) } } } else { # Was the next line but discovered those get handled above easily # $properties["#text"] = $element.InnerText } } if (![string]::IsNullOrWhiteSpace($element.BaseURI)) { $properties["BaseURI"] = $element.BaseURI } if (![string]::IsNullOrWhiteSpace($element.NamespaceURI)) { $prefix = "schema" if (![string]::IsNullOrWhiteSpace($element.Prefix)) { $prefix = $element.Prefix } $properties[$element.Prefix] = $element.NamespaceURI } } else { # Check if the input is an array or collection. If so, we also need to convert # those types into hash tables as well. This function will convert all child # objects into hash tables (if applicable) if ($InputObject -is [System.Collections.IEnumerable] -and $InputObject -isnot [string]) { $collection = @( foreach ($object in $InputObject) { (ConvertTo-Hashtable -InputObject $object -Recursing) } ) # Return the array but don't enumerate it because the object may be pretty complex Write-Output -NoEnumerate $collection return } elseif ($InputObject -is [psobject]) { # If the object has properties that need enumeration # Convert it to its own hash table and return it foreach ($property in $InputObject.PSObject.Properties.Where({$_.MemberType -eq 'NoteProperty' -or $_.MemberType -eq 'Property'})) { $properties[$property.Name] = (ConvertTo-Hashtable -InputObject $property.Value -Recursing) } } else { # If the object isn't an array, collection, or other object, just return it and hope for the best return $InputObject } } if ($Recursing) { return $properties } else { return (New-Object PSCustomObject -Property $properties) } }