Bulk create variables from XmlLinkedNode

Hello !
I need some help to bulk create variables from an xml file content. Let me explain by powershell.
I’m executing the following code:

[xml]$XmlLTI = Get-Content C:\Users\AdminDell\Desktop\HOLDING\LTI-HOLDING-v0\bin\x64\Settings.xml
$XmlLTI.countries.country | Where-Object CountryDisplayName -eq 'China'
$test = $XmlLTI.countries.country | Where-Object CountryDisplayName -eq 'China'
$test

The result is :

CountryCode         : CHN-W10
ADDomainNetbiosName : CHINA
ADDomainFQDN        : xxx
ADOrgUnit           : AdOrgUnit
ADJoinDomainUser    : user1
...

The question is : how to dynamically create variables foreach element under $Test.xxx (the name and count of elements can change) ?

  • $CountryCode = CHN-W10
  • $ADDomainNetbiosName = CHINA

Thank you <3

GiTong,
Welcome to the forum. :wave:t4:

In the vast majority of the cases that is unnecessary in PowerShell and indicates a missunderstanding of the way PowerShell works.

To answer your question anyway - you would use a loop. :wink:

Either with

or

You can create new variables you don’t know the name of yet with

You may elaborate a liitle more detailed about what you’re actually want to do and we might be able to help you step further.

1 Like

Thank you for your help. More context: i have a graphical interface with a combobox, the user choose a country. The script reads the xml, retrieve the attributes for this country, then display it to the next screen and do lot of others tasks (domain join, registration …) it’s why i need these variables to be created.

Thanks for the foreach-object that’s the trick , but i don’t know how to separate the “left” attribute and the right “value”
example :

$test | ForEach-Object {$_}
CountryDisplayName  : China

I’m still not convinced that you need to create variables since PowerShell creates loop variables automatically when you use a loop.

In PowerShell we work with objects and properties. So if you search for you should search for “properties” - not “left attributes” :wink:

We use the so called dot notation to access the properties of an object.

So it’s either this:

$test | 
    ForEach-Object {
        $_.CountryDisplayName
    }

or this:

foreach ($element in $test) {
    $element.CountryDisplayName
}

The latter one is much faster most of the times. :wink:

Sorry, i think my request is not clearly understood. I would like to create as many variables as the number of properties in my object $Test.
More clear: $Test (which is a xmlview type) has multiple properties

  • $Test.CountryCode is CHN-W10
  • $Test.ADDomainNetbiosName : CHINA

  • i want to find all the existing properties for $Test (this is not a fixed number and properties names) , then create the variable $CountryCode, ADDomainNetbiosName , and store the value in this variable :slight_smile:

Hmmm … and I think you didn’t understand what I was trying to explain. In 99.99% of the cases that’s not necessary.

I’ve got this.

Even if I’m still not convinced that this is needed I already said what you need - a loop and New-Variable

Please share some sanitized sample data of your XML file (formatted as code, please) and explain what you want to do with the variables you think you need to create.

Here it is :

<?xml version="1.0" encoding="utf-8"?>
<countries>
<country>
    <CountryDisplayName>China</CountryDisplayName>
    <CountryCode>CHN-W10</CountryCode>
    <ADDomainNetbiosName>CHINA</ADDomainNetbiosName>
    <OGID>CHN-W10</OGID>
    <StagingUser>stagingUser1</StagingUser>
    <Regex></Regex>
</country>
<country>
    <CountryDisplayName>Honk-Kong</CountryDisplayName>
    <CountryCode>HKG-W10</CountryCode>
    <ADDomainNetbiosName>HONGKONG</ADDomainNetbiosName>
    <OGID>WS1OGID>HKG-W10</OGID>
    <StagingUser>stagingUser2</StagingUser>
    <Regex>123456789</Regex>
	<VarXYZ>abcdef</VarXYZ>
	<VarABC>xyz</VarABC>
</country>
</countries>

I put more info below .

Here is one part of the xml.
I need a function that will create the variables depending the CountryDisplaName.

Set-VariablesFromXML -xml $xml -country “China” > creates all variables in the China node ($CountryDisplaName, $CountryCode … with their repective values China, CHN-W10 …)
Each node can have more or less variables.

<?xml version="1.0" encoding="utf-8"?>
<countries>
<country>
    <CountryDisplayName>China</CountryDisplayName>
    <CountryCode>CHN-W10</CountryCode>
    <ADDomainNetbiosName>CHINA</ADDomainNetbiosName>
    <OGID>CHN-W10</OGID>
    <StagingUser>stagingUser1</StagingUser>
    <Regex></Regex>
</country>
<country>
    <CountryDisplayName>Honk-Kong</CountryDisplayName>
    <CountryCode>HKG-W10</CountryCode>
    <ADDomainNetbiosName>HONGKONG</ADDomainNetbiosName>
    <OGID>WS1OGID>HKG-W10</OGID>
    <StagingUser>stagingUser2</StagingUser>
    <Regex>123456789</Regex>
	<VarXYZ>abcdef</VarXYZ>
	<VarABC>xyz</VarABC>
</country>
</countries>

You still don’t say whatfor you need all these variables.

Here is how to extract the node names:

[XML]$XMLInput = 
@'
<?xml version="1.0" encoding="utf-8"?>
<countries>
<country>
    <CountryDisplayName>China</CountryDisplayName>
    <CountryCode>CHN-W10</CountryCode>
    <ADDomainNetbiosName>CHINA</ADDomainNetbiosName>
    <OGID>CHN-W10</OGID>
    <StagingUser>stagingUser1</StagingUser>
    <Regex></Regex>
</country>
<country>
    <CountryDisplayName>Honk-Kong</CountryDisplayName>
    <CountryCode>HKG-W10</CountryCode>
    <ADDomainNetbiosName>HONGKONG</ADDomainNetbiosName>
    <OGID>WS1OGID>HKG-W10</OGID>
    <StagingUser>stagingUser2</StagingUser>
    <Regex>123456789</Regex>
	<VarXYZ>abcdef</VarXYZ>
	<VarABC>xyz</VarABC>
</country>
</countries>
'@ 

$XMLInput.countries.country[0].psobject.BaseObject | 
Get-Member | 
Where-Object -Property MemberType -EQ -Value Property | 
Select-Object -Property Name

This outputs the node names of the first country node. For the second one you use [1] and so on. And for all of them you use a loop. :wink:

THe output for the first is this:

Name
----
ADDomainNetbiosName
CountryCode
CountryDisplayName
OGID
Regex
StagingUser

… and for the second node it’s this:

Name
----
ADDomainNetbiosName
CountryCode
CountryDisplayName
OGID
Regex
StagingUser
VarABC
VarXYZ
1 Like

Just to put my 2 pennies in:

$XMLInput.Countries.Country

Will also give you what you are looking for (using Olaf’s example).
You can then do things like:

$XMLInput.Countries.Country[0]

To give you the first element and all its properties.
You don’t need to separate them out into separate variables, they can be happily nested.

1 Like

You still don’t say whatfor you need all these variables.
i thought my answer was clear, do you need more details ?
> The script reads the xml, retrieve the attributes for this country, then display it to the next screen and do lot of others tasks (domain join, registration …) it’s why i need these variables to be created.

I think you missunderstood.

You may show your code. You don’t need to create variables to display the properties and / or the values. You can use the existing properties and values of the instance of the objects created by PowerShell from your input XML.

One issue with programmaticall created variables with arbitrary names is to enumerate them later on.

1 Like

Finally i did it with your help, sorry if it is not the way to do, sure it can be done better, but it allow me to do what i need and that’s make me happy :slight_smile: Sometimes, the best is the ennemy of the good :wink:

Here is the code:

$ComboBoxResult = $XmlLTI.countries.country | Where-Object CountryDisplayName -eq 'China'
$NodesList = $ComboBoxResult.psobject.BaseObject | Get-Member | Where-Object -Property MemberType -EQ -Value Property | Select-Object -Property Name
foreach ($Node in $NodesList) {
    Write-host "create new variable $($Node.Name) with value $($ComboBoxResult.$($Node.Name))  "  
    New-Variable -Name $($Node.Name) -Value $($ComboBoxResult.$($Node.Name)) -Force
    }

OK. I’m glad it helped. :+1:t4:

But now I’m curious. How do you use these variables? :thinking: You don’t know their names in advance. :man_shrugging:t4:

Yes Olaf you are totally right, but i’m using these values lot of time in my script, and it’s really easier to create it all altough there is few unused . Thank you again.

Hmmm … no - I am actually curious. Could you explain or show how you use these programmatically created variables later on?

example 1: exporting to another xml file :


[xml]$LTIXML = Get-Content -Path $LTIRESULTSXML
			$LTIXML.LTIRESULTS.country.CountryDisplayName = $CountryDisplayName
			$LTIXML.LTIRESULTS.country.CountryCode = $CountryCode
			$LTIXML.LTIRESULTS.JoinDomain.ComputerName = $tpcname.ToUpper() ...

example 2: displaying value in the gui

	#Set variables
	$labelSummaryValue1.text = $Summarylabel1Value
	$labelSummaryValue2.text = $CountryDisplayName
	$labelSummaryValue3.text = $combobox1.text.ToUpper()
	$labelSummaryValue4.text = $ADDomainNetbiosName
	
	#Set OU 
	$labelSummaryValue5.text = $ADOrgUnit #OU Cible

hmmm … I’m afraid we do not talk about the same topic. I was curious how you use variables you created programmatically when you’re actually not know in advance what their names are.

I’m not using those that i don t know in the main script :slight_smile: but it was quicker to use the loop to create all the variables based on the xml than specifying it all one by one.

Hmmm … that’s actually what I meant. I’d consider this as unnecessary cumbersome complex. In this case you can simply use the XML variable reference … like this: $XmlLTI.countries.country :man_shrugging:t4:

But thanks anyway for explaining. :+1:t4:

1 Like