How to construct multiple depth hashtable

Hello
I am currently writting a script that constrcut a hashtable from xml and reconstruct object with the hashtable


function import-xml([xml]$xml){



foreach ($object in $xml) {
    
  
}

}

function getproperty($currentproperty) {
    foreach ($property in $object){
        if ($currentproperty=$null) {
            $currentproperty = $property
        }
        
        $currentProperty|ForEach-Object{
        
            if ($property.property) {
                getproperty $property
            }
            else {
                rehydrate $property
            }
        }
        
        
            }
        
    
}
function rehydrate($property){


    $a=New-Object array
    $object=New-Object $property.type
if ($property.Value) {
foreach($value in $property){
    $a.add($value)
    
}
   $a = $a-join ","
   Invoke-Expression '$object=($a) '
   $object
}

elseif ($property.NoteProperty) {
    $psobject = New-Object $property.type
    foreach($noteproperty in $property){

        $psobject|Add-Member $noteproperty.name $noteproperty.innertext
    }
    $psobject
}
elseif ($property.key) {

    $hashtable =New-Object $property.type

    foreach ($key in $property) {
        $hashtable[$key.name]=$key.innertext

    }
}
else {
    
}


}

the function will get the property from xml i save before and reconstruct a hashtable which will be used for construct object
but i having trouble building the hashtable
i could build a hashtable like this easily

$HASHTABLE =@{
X=1
Y=1
Z=1}

i don’t know how to build a hashtable with mulitiple depth like this in script

$hashtable=@{
    roadcoordinate=@{

        roadcoordinate1=@{
            x=1
            y=1
            z=1
        }
        roadcoordinate2=@{
            x=1
            y=1
            z=1

        }
    }

    dimension="the_End"
    name=$null
}

Here is the xml which i used

<?xml version="1.0" encoding="utf-8"?>
<Objects>
<Object Type="test">
  <Property Name="param1" Type="System.String">
  <value>1</value>
  </Property>
  <Property Name="param2" Type="System.Int32">
  <value>2</value>
  
  </Property>
  <Property Name="param3" Type="array">
<value>1</value>
<value>2</value>
<value>3</value>
  </Property>
  
  <Property Name="param4" Type="System.Management.Automation.PSCustomObject">
    
<noteproperty name="database">
database
</noteproperty>

<noteproperty name="server">server</noteproperty>

<noteproperty name="username">username</noteproperty>

<noteproperty name="password">password</noteproperty>

</Property>
    
<Property Name="param5" Type="System.Collections.Hashtable">

<key name=color>red</key>
<key name=type>fruit</key>
<key name=name>apple</key>
</property>
<property name= "param6" type="road">
<property name= "roadcoordinate" type ="roadcoordinate">
<property name="roadcoordiate1" type = "System.Numerics.Vector3">
<property name ="x" type= "system.int32">
<value>1</value>
</property>
<property name ="y" type= "system.int32">
<value>1</value>
</property>
<property name ="z" type= "system.int32">
<value>1</value>
</property>
</property>
<property name= "roadcoordinate2" type = "System.Numerics.Vector3">

</property>
</property>
</property>
<property name="id"></property>
<property name="dimension"></property>
<property name="name"></property>
</property>
</Objects>

I’m unsure if I’ve got what exactly you’re looking for … do you know about the cmdlets

and

?

I would suggest you start by looking at PowerShell objects. Objects will convert more easily to xml than hash tables. Here is how to make your sample data into a PS object with levels.

$object=[PSCustomObject]@{
    roadcoordinate=[PSCustomObject]@{
        roadcoordinate1=[PSCustomObject]@{
            x=1
            y=1
            z=1
        }
        roadcoordinate2=[PSCustomObject]@{
            x=1
            y=1
            z=1
        }
    }
    dimension="the_End"
    name=$null
}

Once you get the object, then I suggest finding all the XML related commands in PowerShell.
Get-Command *xml*

1 Like

yes ,but import/export-clixml wouldn’t import the object itself i would import the deserize object instead ,so i need to find a new way to try to import the object ,which i am doing now is try to save the object detail in xml and reconstruct it from the xml

That’s waht I meant with …

With Import-CliXml you could re-create an object or multiple objects from an XML file you saved earlier with Export-CliXml. Where do you get your XML file from? What is it you’re actually trying to do? … the bigger picture … ?? :thinking: :wink:

Yes,thanks for the advice
I am currently rely on hashtable because most of the powershell class, ([System.Numerics.Vector3])for example would support the hashtable overload,so once i get the hashtable i could input and reconstruct it easily .

I am trying to reconstruct the object from xml i saved before.
and as for the xml was a different function.
here is the github repo for the function

hmmm … since there’s not that much of documentaion and I don’t like to digg into the code that much yet … is there a particular reason why you’re not using Export-Clixml for the export? … sound’s like you’re trying to re-invent the wheel … :wink:

Because when using import/export-clixml ,it wouldn’t input the object itself
The different is deserize object doesn’t work well with overload
And deserize object doesn’t have the method from previous object.
So it just a similar object that export from the object and not the real object,so there would be some trouble working with it.
And i would like to build a function that could create real object from the XML instead of creating a similar one

Hmmm … ok … and how did you create the objects in the first place? … I mean before you saved them to XML?

And what would you like to do with the recreated objects? What method is / methods are missing? Do you really need these methods?

Here is the code i found on google that work with unlimited depths construct

function ConvertFrom-Xml {
<#
.SYNOPSIS
    Converts XML object to PSObject representation for further ConvertTo-Json transformation
.EXAMPLE
    # JSON->XML
    $xml = ConvertTo-Xml (get-content 1.json | ConvertFrom-Json) -Depth 4 -NoTypeInformation -as String
.EXAMPLE
    # XML->JSON
    ConvertFrom-Xml ([xml]($xml)).Objects.Object | ConvertTo-Json
#>
    param([System.Xml.XmlElement]$Object)

    if (($Object -ne $null) -and ($Object.Property -ne $null)) {
        $PSObject = New-Object PSObject

        foreach ($Property in @($Object.Property)) {
            if ($Property.Property.Name -like 'Property') {
                $PSObject | Add-Member NoteProperty $Property.Name ($Property.Property | % {ConvertFrom-Xml $_})
            } else {
                if ($Property.'#text' -ne $null) {
                    $PSObject | Add-Member NoteProperty $Property.Name $Property.'#text'
                } else {
                    if ($Property.Name -ne $null) {
                        $PSObject | Add-Member NoteProperty $Property.Name (ConvertFrom-Xml $Property)
                    }
                }
            } 
        }   
        $PSObject
    }
}

I don’t really understand what you mean
But in general deserize object is not the object itself so there will be trouble working with them

This makes no sense to me. Even if you reconstruct it manually it still won’t be the object. You are just doing custom deserialization??

1 Like

I figured … :smirk:

You stated that the recreated object misses some methods the original object had. Do you really need these methods for further steps? Or is it just to satisfy your OCD? :wink: What methods do you miss? And what objects do we actually speak about?

That’s why I asked what you want to do with the objects when you re-created them … what is the actual goal of ALL THIS?

How are these objects created in the first place? Why do you need to serialize them?

You may spend a lot of effort for almost no benefit. :man_shrugging:t3:

Thx for asking
Here is the Idea of how i reconstruct the object from xml,and how i store the xml from object

here is the example class i build for test the function
class test

using namespace system.xml.linq
class test {
[string]$param1
[int]$param2
[array]$param3
[psobject]$param4
[hashtable]$param5


hidden $path="c:\Users\é‚“ć·±\test.xml"

test($param1,$param2,$param3,$param4,$param5) {
$this.param1=$param1
$this.param2=$param2
$this.param3=$param3
$this.param4=$param4
$this.param5=$param5

}
[object] save(){


$xml =[XElement]::new("test",
[XElement]::new("param1",

[XElement]::new("string",($this.param1|foreach-object {

  [XElement]::new("value",$_)
})


),
[XElement]::new("type","value")

),
[XElement]::new("param2",
[XElement]::new("int",($this.param2|foreach-object {

  [XElement]::new("value",$_)
})

),
[XElement]::new("type","value")
),
[XElement]::new("param3",
[XElement]::new("array",($this.param3|foreach-object {

  [XElement]::new("value",$_)
})



),
[XElement]::new("type","value")


)
,
[XElement]::new("param4",
[XElement]::new("psobject",
(($this.param4|Get-Member -Type NoteProperty |Select-Object -Property name).name|foreach-object{

[XElement]::new("$_",$this.param4.$_)

})


),
[XElement]::new("type","name")

)
,
[XElement]::new("param5",
($this.param5.keys|foreach-object{
  [XElement]::new("key",
  [XElement]::new("name",$_),
  [XElement]::new("value",$this.param5[$_])
  
  )

}
),
[XElement]::new("type","key")

)
)
return $xml.tostring()

}


test ($property){
  $this.doinit($property)
}
doinit([pscustomobject]$property){
  foreach($name in $property.name){
    $this.$name =$property.$name
  }

}

    }
    
    $param4= New-Object PSObject -Property @{
    Name='New'
    Server = 'server'
    Database = 'database'
    UserName = 'username'
    Password = 'password'
}
$param5=[hashtable]@{
  name ='apple'
  type='fruit'
  color='red'
}
 
    
    

the save() method will save the xml file in hidden path for which i will use to reconstruct the object .



function import-xml([xml]$xml){



foreach ($object in $xml) {
    
  
}

}

function getproperty($currentproperty) {
    foreach ($property in $object){
        if ($currentproperty=$null) {
            $currentproperty = $property
        }
        
        $currentProperty|ForEach-Object{
        
            if ($property.property) {
                getproperty $property
            }
            else {
                rehydrate $property
            }
        }
        
        
            }
        
    
}
function rehydrate($property){


    $a=New-Object array
    $object=New-Object $property.type
if ($property.Value) {
foreach($value in $property){
    $a.add($value)
    
}
   $a = $a-join ","
   Invoke-Expression '$object=($a) '
   $object
}

elseif ($property.NoteProperty) {
    $psobject = New-Object $property.type
    foreach($noteproperty in $property){

        $psobject|Add-Member $noteproperty.name $noteproperty.innertext
    }
    $psobject
}
elseif ($property.key) {

    $hashtable =New-Object $property.type

    foreach ($key in $property) {
        $hashtable[$key.name]=$key.innertext

    }
}
else {
    
}


}

the import-xml will convert the saving xml into object by converting into pscustom object then reconstruct the object by Doinit the pscustom object

I give up. You’re not answering any question. And it seems like you’ve found a solution for what you want anyway. Good luck!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.