none
Pipeline object to a function and create a XML with it RRS feed

  • Question

  • I'm trying to create XML files with a object as input tough a pipeline:

    Get-ActiveDirectoryForest -Domain $Domain | GenerateXml


    How can I pass a object to a other function and use this object to create a XML file?I'm currently stuck at object errors and weird looking XML files.

    The object that get's passed throug always has the same first Property (TableName), the rest is different.

    My Object looks like:

    TableName                   Domain      User        Status      UNC
    Network-Domain-Locked users test.local  John Doe    Locked      John.Doe@test.local
    Network-Domain-Locked users test.local  Jane Doe    Locked      Jane.Doe@test.local


    And the function that I've created:

    Function GenerateXml {
    [CmdLetBinding()]
        Param (
            [parameter(Mandatory=$True, ValueFromPipelineByPropertyName=$True)]
            [Object]$Object,
    
            [parameter(Mandatory=$True, ValueFromPipelineByPropertyName=$True)]
            [String]$TableName
        )
        Begin {
    
            $XmlExportPath = $Script:Settings.XmlFolder
            If ((Test-Path -Path $XmlExportPath\export.xml)) {
                Remove-Item -Path $XmlExportPath\export.xml -Force
            }
    
    Add-Content -Path $XmlExportPath\export.xml -Value @'
    <?xml version="1.0" encoding="utf-8"?>
    <ImportFile>
        <Module Name="Network-Collection">
            <Task>Test export object</Task>
        </Module>
        <Input TableName="$TableName">
    '@
        }
        Process {
            Try {
                $TableName = $Object.TableName  #Can't find the property on the object..
                Write-Host "Database tabel: $TableName"
    
                $(foreach ($Item in $Object) {
                    Add-Content -Path $XmlExportPath\export.xml -Value '@`t`t<$($Item.Key)>$($Item.Value)</$($Item.Key)>@'
                })
            }
            Catch { Write-Error $_ }
        } 
        End {
    Add-Content -Path $XmlExportPath\export.xml -Value @'
        </Input>
    </BitImportFile>
    '@
        } # End Region
    }

    Thanks for your thoughts!

    Regards, Paul

    • Moved by Bill_Stewart Wednesday, September 13, 2017 9:00 PM Abandoned
    Wednesday, July 19, 2017 2:15 PM

All replies

  • $object | ConvertTo-Xml | Out-File $XmlExportPath\export.xml

    \_(ツ)_/



    • Edited by jrv Wednesday, July 19, 2017 5:46 PM
    Wednesday, July 19, 2017 5:44 PM
  • You can also manually build XML using the XMLDocument class.

    $tablename = 'SomeTable'
    [xml]$xml = @'
    <?xml version="1.0" encoding="utf-8"?>
    <ImportFile>
        <Module Name="Network-Collection">
            <Task>Test export object</Task>
        </Module>
        <Input TableName="$TableName"/>
    </ImportFile>
    '@
    

    Now use createElement and appendChild to create correctly formed XML.

    Save it:

    $xml.Save($filename)


    \_(ツ)_/

    Wednesday, July 19, 2017 5:53 PM
  • But should I implement this with the Begin, Process, End parts? In my understanding Begin / End gets proccesed once and Process is started for each member in a pipline object like: (Get-Process | GenerateXml).

    If I create the XML in the process part then this means I'll get many XML files and this should be one. Thats why the header is in the Begin section and the footer in End, only the repeated parts are in the Process block.

    Hmm, or should I create the XML variable in Begin, append to it in Process and write the variable with $XML.Save in End?...

    Thursday, July 20, 2017 6:41 AM
  • Your question has nothing to do wit creating an XML file. Forgot about functions. Just write the code to crate the XML correctly.   After yu understand how that works you can try to crate a function that uses a pipeline. 

     

    \_(ツ)_/

    Thursday, July 20, 2017 7:51 AM
  • Hi @jrv,

    I've found the awnser and posted some sample code below. Please let me know if I should make improvements or if you spot any errors in it.

    Function GenerateXml {
    
    [CmdLetBinding()]
    
        Param (
            [parameter(ValueFromPipelineByPropertyName=$True)]
            [Object]$Object,
            
            [parameter(ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
            [String]$TableName
        )
    
        Begin {
            $XmlExportFile = "C:\Temp\Export.xml"
    
            [xml]$Xml = @'
    <?xml version="1.0" encoding="utf-8"?>
    <ImportFile>
        <Module Name="" Date="" />
        <Input TableName="">
        </Input>
    </ImportFile>
    '@
        }
    
        Process {
            Try {
                $XmlNode = $Xml.ImportFile
                $XmlNode.Module.Name = $_.TaskName
                $XmlNode.Input.TableName = $_.TableName
                $XmlProperties = $_.PSObject.Properties
                
                Foreach ($XmlProp in ($XmlProperties | Where-Object {$_.Name -ne "TaskName" -and $_.Name -ne "TableName"})) {
                    $Name = $XmlProp.Name
                    $Value = $XmlProp.Value
    
                    $newRole = $xml.CreateElement($Name)
                    $Xml.ImportFile.Input.AppendChild($newRole) | Out-Null
                    $newRole.SetAttribute("Value",$Value);
                }
            }
            Catch { Write-Error $_ }
        } 
    
        End {
            $Xml.Save("$XmlExportFile")
        }
    }

    Saturday, July 22, 2017 8:53 AM
  • If you are trying to save a data table as XML that function is built into the table object. It can be saved with or without the schema.


    \_(ツ)_/

    Saturday, July 22, 2017 9:03 AM