Convert XML to PSObject; Identical child nodes to Array

Viewed 43

So I have been beating my head against the wall for about a day now on this and I am struggling to create a elegant, or working for that matter, solution.

Background

The script I am working on is a universal application installer that we can pair with our application deployment software but also be usable by on-site admins to ensure all applications are always deployed identically and to really simplify the application deployment process overall.To make the configuration files as simple as possible to create, I have went with xml files. Because PowerShell has a fairly suboptimal way to interface with XML files I am importing the configuration file as a PSObject. This works perfectly except when a XML child node is present multiple times which often happens.

Issue

I am trying to get child nodes with identical names to grouped into an Array object. (Example: $Result | Add-Member -MemberType:'NoteProperty' -Name:($tXML.name) -Value:$(Array of PSObjects;) In this case both of the installer xml nodes). The desired result would be something similar to this. I have isolated the Parent Node definition to SystemObject so in the XML below it calls the SystemObject node case twice (once for installer and once for uninstaller) but I can't figure out how to add the child nodes to a functioning array in the desired format.

Example Picture

Desired Output

Function

Function Convert-XMLtoPSObject {
    Param (
        $XML
    )
    New-Variable -Name:'Result' -Value:(New-Object -TypeName:'PSCustomObject')

    $xml | Get-Member -MemberType:'Property' |
    Where-Object {
        $_.MemberType -EQ 'Property'
    } | ForEach-Object -Process:{
        $tXML = $_
        Switch -Regex ($_.Definition) {
                '^\bstring\b.*$' {
                    $Result | Add-Member -MemberType:'NoteProperty' -Name:($tXML.Name) -Value:($XML.($tXML.Name))
                }
                '^\bSystem\.Object\b\[] (?!#comment).*$' {
                    Write-Host "SystemObject Baby!"
                }
                '^\bSystem.Xml.XmlElement\b.*$' {
                    $Result | Add-Member -MemberType:'NoteProperty' -Name:($tXML.Name) -Value:(
                        Convert-XMLtoPSObject -XML:($XML.($tXML.Name))
                    )
                }
                '^\bSystem\.Object\b\[] (#comment).*$' { <# Do Nothing #> }
            Default {
                Write-Host "Unrecognized Type: $($tXML.Name)='$($tXML.Definition)'"
            }
        }
    }
    $Result
}

install.xml

<AppInstall>
    <GlobalConfig>
        <Directory>{$ConfigDir}</Directory>
        <!-- [String] Install flags to append to all installers. -->
        <InstallFlags></InstallFlags>
        <!-- [ScriptBlock] PowerShell script used to test if this AppInstaller should run. -->
        <!-- Note: Should return True of False -->
        <FilterScript></FilterScript>
    </GlobalConfig>

    <Uninstallers>
        <Uninstaller>
            <ID>0</ID>
            <!-- [String] Search String to try to find in registry -->
            <SearchString></SearchString>
            <!-- [string] How to search for search string. -->
            <!-- Options: Simple, Regex, Exact-->
            <SearchType></SearchType>
            <!-- [String] Attempts to uninstall installers of specific architectures. -->
            <!-- Options: x64, x32, Both -->
            <Architecture></Architecture>
            <!-- [String] Flags to add to uninstaller. -->
            <Flags></Flags>
            <!-- [Bool] Attempt to extract the uninstaller path. -->
            <URLExtraction></URLExtraction>
        </Uninstaller>
        <Uninstaller>
            <ID>0</ID>
            <!-- [String] Search String to try to find in registry -->
            <SearchString></SearchString>
            <!-- [string] How to search for search string. -->
            <!-- Options: Simple, Regex, Exact-->
            <SearchType></SearchType>
            <!-- [String] Attempts to uninstall installers of specific architectures. -->
            <!-- Options: x64, x32, Both -->
            <Architecture></Architecture>
            <!-- [String] Flags to add to uninstaller. -->
            <Flags></Flags>
            <!-- [Bool] Attempt to extract the uninstaller path. -->
            <URLExtraction></URLExtraction>
        </Uninstaller>
    </Uninstallers>

    <Installers>
        <Installer>
            <!-- [Int] Order in which installer functions will run. -->
            <ID>0</ID>
            <!-- [String] What OS architecture the installer will run under. -->
            <!-- Options: x64, x32, Both -->
            <Architecture>x64</Architecture>
            <!-- [String] What flags should be added to the installer. -->
            <Flags>/QN</Flags>
            <!-- [int[]] Comma seperated list of which uninstallers to run and in what order before installing. -->
            <RunUninstallers></RunUninstallers>
            <!-- [ScriptBlock] PowerShell script used to test if this installer should run. -->
            <!-- Note: Should return True of False -->
            <FilterScript></FilterScript>
            <!-- Directory path to be added to parent GlobalConfig directory -->
            <InstallFile>\x64\install.msi</InstallFile>
        </Installer>
        <Installer>
            <!-- [Int] Order in which installer functions will run. -->
            <ID>1</ID>
            <!-- [String] What OS architecture the installer will run under. -->
            <!-- Options: x64, x32, Both -->
            <Architecture>x32</Architecture>
            <!-- [String] What flags should be added to the installer. -->
            <Flags>/QN</Flags>
            <!-- [int[]] Comma seperated list of which uninstallers to run and in what order before installing. -->
            <RunUninstallers></RunUninstallers>
            <!-- [ScriptBlock] PowerShell script used to test if this installer should run. -->
            <!-- Note: Should return True of False -->
            <FilterScript></FilterScript>
            <!-- Directory path to be added to parent GlobalConfig directory -->
            <InstallFile>\x32\install.msi</InstallFile>
        </Installer>
    </Installers>
</AppInstall>
0 Answers
Related