- I'm trying to create an object the will hold computer name with it's relevant ip address
- I have the following XML that maps all my computers with their ips:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<hq>
<dbs>
<db>
<ip>153.77.162.62</ip>
<cn>SRRAALABJHQDB</cn>
</db>
</dbs>
<mbs>
<mb>
<ip>153.77.162.63</ip>
<cn>SRRAALABJHQRBT</cn>
</mb>
</mbs>
<apps>
<app>
<ip>153.77.162.61</ip>
<cn>SRRAALABJHQIIS</cn>
</app>
</apps>
<sts>
<st>
<dbs>
<db>
<ip>153.77.162.64</ip>
<cn>SRRAALABJST1</cn>
</db>
</dbs>
<mbs>
<mb>
<ip>153.77.162.64</ip>
<cn>SRRAALABJST1</cn>
</mb>
</mbs>
<apps>
<app>
<ip>153.77.162.64</ip>
<cn>SRRAALABJST1</cn>
</app>
</apps>
<poss>
<pos>
<dbs>
<db>
<cn>DTRAALABJPOS1</cn>
</db>
</dbs>
<apps>
<app>
<ip>153.77.162.66</ip>
<cn>DTRAALABJPOS1</cn>
</app>
</apps>
</pos>
<pos>
<dbs>
<db>
<cn>DTRAALABJPOS2</cn>
</db>
</dbs>
<apps>
<app>
<ip>153.77.162.67</ip>
<cn>DTRAALABJPOS2</cn>
</app>
</apps>
</pos>
</poss>
</st>
<st>
<buid>100</buid>
<dbs>
<db>
<ip>153.77.162.65</ip>
<cn>SRRAALABJST2</cn>
</db>
</dbs>
<mbs>
<mb>
<ip>153.77.162.65</ip>
<cn>SRRAALABJST2</cn>
</mb>
</mbs>
<apps>
<app>
<ip>153.77.162.65</ip>
<cn>SRRAALABJST2</cn>
</app>
</apps>
<poss>
<pos>
<dbs>
<db>
<cn>DTRAALABJPOS3</cn>
</db>
</dbs>
<apps>
<app>
<ip>153.77.162.68</ip>
<cn>DTRAALABJPOS3</cn>
</app>
</apps>
</pos>
</poss>
</st>
</sts>
</hq>
I need to create an Object that hold value along side to value (cn is short of Computer Name)
I tried the following script to create such an object:
$path = "C:\lab_j.xml"
[xml] $lab = Get-Content -Path $Path
$vms = $lab | Select-Xml "//cn" | ForEach-Object { $_.Node.InnerText } | Select-Object -Unique
$ips = $lab | Select-Xml "//ip" | ForEach-Object { $_.Node.InnerText } | Select-Object -Unique
$vmObject = New-Object PSObject
Foreach ($vm in $vms) {
if ([bool]($vmObject.psobject.Properties | where { $_.Name -eq "name"})) {
$vmObject.name = $vm
}
else
{
$vmObject | Add-Member -MemberType NoteProperty -Name 'name' -Value $vm -Force
}
}
Foreach ($ip in $ips) {
if ([bool]($vmObject.psobject.Properties | where { $_.Name -eq "ip"})) {
$vmObject.ip = $ip
}
else
{
$vmObject | Add-Member -MemberType NoteProperty -Name 'ip' -Value $ip -Force
}
}
- the output of $vmObject give only one "entry":
PS C:\Users\hiddai> $vmObject
name ip
---- --
DTRAALABJPOS3 153.77.162.68
instead of:
PS C:\Users\hiddai> $vmObject
name ip
---- --
SRRAALABJHQDB 153.77.162.62
SRRAALABJHQRBT 153.77.162.63
SRRAALABJHQIIS 153.77.162.61
SRRAALABJST1 153.77.162.64
DTRAALABJPOS1 153.77.162.66
DTRAALABJPOS2 153.77.162.67
SRRAALABJST2 153.77.162.65
DTRAALABJPOS3 153.77.162.68
- Is there a short and simple way to create such an object?
CodePudding user response:
the output of $vmObject give only one "entry":
That's because you only ever create 1 object, then keep overwriting it's values.
Is there a short and simple way to create such an object?
Yes, you can use a single XPath query to find any XML element that has a <cn>
and an <ip>
child node, then create the resulting objects using Select-Object
:
$lab.SelectNodes('//*[./cn and ./ip]') |Select-Object @{Name='Name';Expression='cn'},@{Name='IP';Expression='ip'}