private/ConvertTo-SfCountriesAndStatesXml.ps1

function ConvertTo-SfCountriesAndStatesXml {

    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [PSCustomObject] $MetadataModel
    )

    $ErrorActionPreference = 'Stop'
    #[bool] $IsDebug = $DebugPreference -ne 'SilentlyContinue'
    #[bool] $IsVerbose = $VerbosePreference -ne 'SilentlyContinue'

    function ConvertToStatesXml {
        param (
            [PSCustomObject] $State
        )

        [string] $xml = '<states>'
        $xml += ConvertTo-XmlTag 'active' ($State._Status -like 'A*'? 'true' : 'false')
        $xml += ConvertTo-XmlTag 'integrationValue' $State._IntegrationValue
        $xml += ConvertTo-XmlTag 'isoCode' $State._StateCode
        $xml += ConvertTo-XmlTag 'label' $State._Label
        $xml += ConvertTo-XmlTag 'standard' $State._IsStandard -IsTrueFalseNull
        $xml += ConvertTo-XmlTag 'visible' ($State._Status -like '*V'? 'true' : 'false')
        $xml += '</states>'

        return $xml
    }

    function ConvertToCountriesXml {
        param (
            [PSCustomObject] $Country,
            [PSCustomObject[]] $States
        )

        [string] $xml = '<countries>'
        $xml += ConvertTo-XmlTag 'active' ($Country._Status -like 'A*'? 'true' : 'false')
        $xml += ConvertTo-XmlTag 'integrationValue' $Country._IntegrationValue
        $xml += ConvertTo-XmlTag 'isoCode' $Country._CountryCode
        $xml += ConvertTo-XmlTag 'label' $Country._Label
        $xml += ConvertTo-XmlTag 'orgDefault' $Country._IsDefaultCountry -IsTrueFalseNull -DefaultValue 'false'
        $xml += ConvertTo-XmlTag 'standard' $Country._IsStandard -IsTrueFalseNull

        $xml += $(
            foreach ($State in $States) {
                ConvertToStatesXml $State
            }
        ) -join ''

        $xml += ConvertTo-XmlTag 'visible' ($Country._Status -like '*V'? 'true' : 'false')
        $xml += '</countries>'

        return $xml
    }

    [string] $xml =
        '<?xml version="1.0" encoding="UTF-8"?>' +
        '<AddressSettings xmlns="http://soap.sforce.com/2006/04/metadata">' +
        '<countriesAndStates>'

    # --- prep countries and states per country
    [array] $Countries = @(
        @($MetadataModel.Tables._StateAndCountryPicklists) |
        Where-Object { $_._StateCode -eq '.' } |
        Sort-Object -Property _CountryCode
    )

    [hashtable] $StatesByCountryCode = @($MetadataModel.Tables._StateAndCountryPicklists) |
        Where-Object { $_._StateCode -ne '.' } |
        Group-Object -Property _CountryCode -AsHashTable -AsString

    # --- do it
    $xml += $(
        foreach ($Country in $Countries) {

            # the @() around the hashtable access creates an empty array in case the country is not present in the hashmap
            [array] $States = @($StatesByCountryCode[$Country._CountryCode] | Sort-Object -Property _StateCode)

            ConvertToCountriesXml $Country $States
        }
    ) -join ''

    $xml +=
        '</countriesAndStates>' +
        '</AddressSettings>'

    return $xml
}