Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's, client's, relative's, descendant's, or tax attorney's.
So I've recently had the task of fetching some information out of system.nfo files to translate cryptic IDs numbers into human readable friendly names. This is the thing that XML is supposed to excel at right? Well you would think that task would be simple enough, and as it turns out it is. However searching for this solution online proved to be difficult, so I'm going to retell my experience here in hopes that it might help anyone else with this problem out.
I started with what I thought was a nice elegant powershell script that would query the XML like a SQL DB and return my value. Seems simple enough right?
$friendlyName = $sysinfo.MsInfo.Category.Category.Category.Data.DeviceName | where {$sysinfo.MsInfo.Category.Category.Category.Data.Device_ID -eq $global:deviceName}
This would work with normal XML where your content is inside the XML tags. However the system.nfo file uses CDATA objects and many nests of categories so you have to go one step further. Since I don't know which Category sub-tree my offending device or data might be in, I ended up grabbing all of the data objects that met my criteria and doing a breadth first search. Sounds ugly compared to the one liner up there, but it actually works and don't take that long. The following code is in powershell. The key here is that handy get_innertext() method. Your standard .Value or .Text won't cut it with CDATA.
# Open the associated .nfo file
$sysinfo_file = $global:computer_name + ".nfo"
$sysinfo_path = $global:computer_name + "\" + $sysinfo_file
[xml]$sysinfo = get-content $sysinfo_path
$nodeList1 = @($sysinfo.GetElementsByTagName("Device_Name"))
$nodeList2 = @($sysinfo.GetElementsByTagName("Device_ID"))
$nodeList3 = @($sysinfo.GetElementsByTagName("Manufacturer"))
$i = 0
foreach($node in $nodeList2)
{
$deviceID = $nodeList2[$i].get_innertext()
if($deviceID -eq $global:device_name)
$friendlyName = $nodeList1[$i].get_innertext()
$deviceManuf = $nodeList3[$i].get_innertext()
}
$i++
The purpose of this handy little script is to look up a cryptic device ID and return a friendly manufacturers name.