Search code examples
xmlpowershell

Convert Dictionary to xml with proper format?


The following script

$d = New-Object -TypeName 'System.Collections.Generic.Dictionary[int, bool]'
$d.Add(1, $true)
$d.Add(2, $false)
($d | ConvertTo-Xml).DocumentElement.OuterXml

returns

<Objects>
  <Object Type="System.Collections.Generic.Dictionary`2[System.Int32,System.Boolean]">
    <Property Name="Key" Type="System.Int32">1</Property>
    <Property Name="Value" Type="System.Boolean">True</Property>
    <Property Name="Key" Type="System.Int32">2</Property>
    <Property Name="Value" Type="System.Boolean">False</Property>
  </Object>
</Objects>

However, can it return the following?

<Objects>
  <Object Key="1" Value="True" />
  <Object Key="2" Value="False" />
</Objects>

Solution

  • Using ConvertTo-Xml (loosely speaking, the in-memory counterpart to Export-CliXml, albeit with a different output format), the closest approximation of the desired format requires adding the -NoTypeInformation switch, which gives you the equivalent of:

    <Objects>
      <Object>
        <Property Name="Key">1</Property>
        <Property Name="Value">True</Property>
        <Property Name="Key">2</Property>
        <Property Name="Value">False</Property>
      </Object>
    </Objects>
    

    Note:

    • In general, ConvertTo-Xml is virtually useless, because the resulting XML format is neither documented nor is there a complementary cmdlet to interpret (deserialize) it.
    • PowerShell (Core) 7, in v7.5+ now offers ConvertTo-CliXml and ConvertFrom-CliXml cmdlets, which use use a standardized XML-based format, CLIXML , which PowerShell uses for cross-process serialization, such as in remoting.

    To get the desired output, you'll have to create the XML manually:

    $d.GetEnumerator() | ForEach-Object { '<Objects>' } {
        '  <Object Key="{0}" Value="{1}" />' -f $_.Key, $_.Value
      } { '</Objects>'}
    

    Note the need to use .GetEnumerator() in order to send the key-value pairs individually through the pipeline; by default, PowerShell doesn't enumerate hashtable/dictionary entries in the pipeline.