Private/Convert-MSIXPSFXML2JSON.ps1

#From https://stackoverflow.com/questions/37024568/applying-xsl-to-xml-with-powershell-exception-calling-transform
function Convert-MSIXPSFXML2JSON {
    [CmdletBinding()]
    param ([Parameter(Mandatory = $true)] [String] $xml, 
        [Parameter(Mandatory = $true)] [String] $xsl, 
        [Parameter(Mandatory = $true)] [String] $output
    )

    Write-Verbose "Converting $xml to $output using $xsl"
    if (-not $xml -or -not $xsl -or -not $output) {
        Write-Host "& .\xslt.ps1 [-xml] xml-input [-xsl] xsl-input [-output] transform-output"
        return $false
    }

    Try {
        $xslt_settings = New-Object System.Xml.Xsl.XsltSettings;
        $XmlUrlResolver = New-Object System.Xml.XmlUrlResolver;
        $xslt_settings.EnableScript = 1;
        $xslt = New-Object System.Xml.Xsl.XslCompiledTransform;
        $xslt.Load($xsl, $xslt_settings, $XmlUrlResolver);
        $xslt.Transform($xml, $output);

        # Normalize: XSLT outputs path values (e.g. VFS\FONTS) and regex patterns (.*\.)
        # with unescaped backslashes — invalid JSON. Fix lone backslashes without touching
        # already-valid \\ pairs. Alternation ensures \\ is consumed as a unit before the
        # engine can split it and misidentify the second \ as the start of a new escape.
        $rawJson = [System.IO.File]::ReadAllText($output, [System.Text.Encoding]::UTF8)
        $rawJson = [System.Text.RegularExpressions.Regex]::Replace(
            $rawJson,
            '(\\\\)|\\([^"\\\/bfnrtu])',
            [System.Text.RegularExpressions.MatchEvaluator]{
                param($m)
                if ($m.Groups[1].Success) { return $m.Value }
                return '\\' + $m.Groups[2].Value
            }
        )
        # ConvertTo-Json (PS 5.1) uses 4-space indentation with no -IndentSize option.
        # Reduce to 2-space indentation and collapse empty arrays/objects to one line.
        $formatted = $rawJson | ConvertFrom-Json | ConvertTo-Json -Depth 20

        # 4 spaces -> 2 spaces per indent level
        $lines = $formatted -split "`r?`n"
        $lines = $lines | ForEach-Object {
            if ($_ -match '^( +)') {
                (' ' * ([int]($Matches[1].Length / 4) * 2)) + $_.TrimStart()
            } else {
                $_
            }
        }

        # Collapse "[\n \n]" and "{\n \n}" patterns to "[]" / "{}"
        $formatted = $lines -join "`n"
        $formatted = [System.Text.RegularExpressions.Regex]::Replace($formatted, '\[\s*\]', '[]')
        $formatted = [System.Text.RegularExpressions.Regex]::Replace($formatted, '\{\s*\}', '{}')

        [System.IO.File]::WriteAllText($output, $formatted, [System.Text.Encoding]::UTF8)
    }

    Catch {
        $ErrorMessage = $_.Exception.Message
        $FailedItem = $_.Exception.ItemName
        Write-Error "Error: $ErrorMessage : $FailedItem : $($_.Exception) ";
        return $false
    }
}