Search code examples
xmlpowershellmember-enumeration

Unable to completely parse XML in PowerShell


I have an XML file that I would like to parse through, and retrieve back specific information.

To make it easy to understand, here is a screenshot of what the XML file looks like:

enter image description here

I would like to parse through the XML and for each Item node, retrieve back the fields indicated in the screenshot. Each of the values retrieved need to be formatted per item node.

Finally, I would love to be able to specify a criteria to look for, and only retrieve that where found.

I have been trying, without luck. Here is what I have been able to come up with:

[xml]$MyXMLFile = gc 'X:\folder\my.xml'
$XMLItem = $MyXMLFile.PatchScan.Machine.Product.Item
$Patch = $XMLItem | Where-Object {$_.Class -eq 'Patch'}
$Patch.BulletinID
$Patch.PatchName
$Patch.Status

When I run the above code, it returns no results. However, for testing purposes only, I remove the Item portion. Now, I can get it working by modifying the code above.

I load the XML into an XML Object. Now I try traverse it down to product and it works perfectly:

PS> $xmlobj.PatchScan.Machine.Product | Select-Object -Property Name, SP

Name SP
---- --
Windows 10 Pro (x64) 1607
Internet Explorer 11 (x64) Gold
Windows Media Player 12.0 Gold
MDAC 6.3 (x64) Gold
.NET Framework 4.7 (x64) Gold
MSXML 3.0 SP11
MSXML 6.0 (x64) SP3
DirectX 9.0c Gold
Adobe Flash 23 Gold
VMware Tools x64 Gold
Microsoft Visual C++ 2008 SP1 Redistributable Gold
Microsoft Visual C++ 2008 SP1 Redistributable (x64) Gold

Now add Item in and Intellisense puts up a bracket as if Item was a method $xmlobj.PatchScan.Machine.Product.Item( ← See that? So that is why I think for some reason the Item node is doing something strange and that is my roadblock.

This screenshot shows better how it starts with many product folders, and then in each product folder is many item folders.

enter image description here

The XML in the product folder I don't care about. I need the individual information in each item folder.


Solution

  • XML is a structured text format. It knows nothing about "folders". What you see in your screenshots is just how the the data is rendered by program you use for displaying it.

    Anyway, the best approach to get what you want is using SelectNodes() with an XPath expression. As usual.

    [xml]$xml = Get-Content 'X:\folder\my.xml'
    $xml.SelectNodes('//Product/Item[@Class="Patch"]') |
        Select-Object BulletinID, PatchName, Status