Loop through xml elements
82,667
Solution 1
Use XPATH instead to find all nodes with a SID attribute like so:
$objs = @()
$nodes = $userfile.SelectNodes("//*[@SID]")
foreach ($node in $nodes) {
$sid = $node.attributes['SID'].value
$dispName = $node.attributes['DISPLAYNAME'].value
$obj = new-object psobject -prop @{SID=$sid;DISPNAME=$dispName}
$objs += $obj
}
$objs
Here's an example with output:
$xml = [xml]@"
<doc>
<foo SID='foosid' DISPLAYNAME="foodisp">
<bar SID='barsid' DISPLAYNAME="bardisp"/>
<baz>
<blech SID='blechsid' DISPLAYNAME="blechdisp"/>
</baz>
</foo>
</doc>
"@
$objs = @()
$nodes = $xml.SelectNodes("//*[@SID]")
foreach ($node in $nodes) {
$sid = $node.attributes['SID'].value
$dispName = $node.attributes['DISPLAYNAME'].value
$obj = new-object psobject -prop @{SID=$sid;DISPNAME=$dispName}
$objs += $obj
}
$objs
Outputs:
SID DISPNAME
--- --------
foosid foodisp
barsid bardisp
blechsid blechdisp
Solution 2
You can also reference the child nodes when you are iterating through the childNodes:
$j.LocalName (the name of the child element)
$j.InnerXml (the Xml content of the child node)
Author by
adean
Updated on March 19, 2020Comments
-
adean about 4 years
I have the following:
$aMyArray = $null [xml]$userfile = Get-Content C:\AppSense\Scripts\AmPolicyConversion\AM_dev.xml $i = 0 FOREACH ($j in $userfile.ChildNodes){ FOREACH($k in $j.DocumentElement) { } $i = $i + 1 }
I am trying to figure out how to loop through each element within powershell.
Then check for an attribute of SID on the element.
If exists get attribute value and put that value into an object and for the same element grab second attribute DISPLAYNAME and place into same object. We will create an array of objects.
I know I am way off but hope you can help.
-
carlpett over 11 yearsCould you add some more detail? Such as, do you know what the xml will look like? Powershell allows you to access by name in that case, which I've found makes code much easier to read
-
-
Anicho over 11 yearsI assume you'd want to add a statement that checks if sid is null before creating multiple new obj empty objects, so you get an array of objs that are relevant.
-
Keith Hill over 11 yearsSince the XPATH specifies that the SID attribute exists on the element, I wouldn't expect a null value for SID - perhaps an empty string.
-
Anicho over 11 yearsyou are correct, I am just saying to be efficient on whats stored in memory. looks like they extracting data of ad based users there might be 1000s so each object would take up x amount of memory, even if they store 0 properties it just saves a bit of space for later on?
-
adean over 11 years@Keith HillThanks for the help, hhowever the above doesn't seem to traverse subnodes
-
adean over 11 yearsI have been using <code> $nodes = $userfile.SelectNodes("/*/*/*[@SID]") </code> to get various levels down but i really need a -recursive to traverse the whole tree. I have working code using find and replace by bringing in the XML file as text but that's more of a workaround than a solution.
-
Keith Hill over 11 yearsThe XPATH expression "//*" says to search every XML element (node), no matter where it is in the hierarchy of elements.