Prof. Powershell

XML Marks the Spot Part 3: Nested Objects

In the final column discussing XML conversion in PowerShell, Jeffrey walks you through converting nested objects to XML.

In the previous lessons we explored converting PowerShell data into a "traditional" XML document. In other words, an XML document that you could use outside of PowerShell. In the last lesson I created a few XML documents using ConvertTo-XML including nested objects. I'll use them for my demonstration.

If you look at cmdlet help you'll discover there is no ConvertFrom-XML cmdlet. Instead you'll get the contents of the XML file, which is just text after all, and tell PowerShell to treat it as an XML document.

PS C:\> [xml]$os = get-content C:\work\myos2.xml
PS C:\> $os

xml                                               Objects
---                                               -------
version="1.0"                                     Objects

The variable $os is now an XML document. I'm not back to where I was when I first converted the Win32_OperatingSystem class to an XML document. I could navigate the document as I showed you previously.

PS C:\> $os.objects

Object
------
Object

But there's actually much more than is presented on the screen as you can see in figure 1.

[Click on image for larger view.] Figure 1.

You can use any of these properties.

PS C:\> $os.objects.object.ChildNodes

[Click on image for larger view.] Figure 2.

When working with XML documents like this, there is an assumption that you know the data. While you can explore an unknown XML file, the more you know what sort of data is in your XML file, the easier (relatively speaking) it is to work with.

PS C:\> $os.objects.object.ChildNodes | where {$_.InnerText} | Select Name,InnerText

As figure 3 shows I'm displaying all properties that have a value.

[Click on image for larger view.] Figure 3.

Instead of filtering on #text, which is awkward because of the # symbol, I'm using the InnerText property which should give me the same value.

Or perhaps it would be easier to turn this back into a PowerShell object. Unfortunately, this is not a trivial task, especially if you have a nested hierarchy of objects.

$file = "C:\work\myos2.xml"
[xml]$xml = get-content -Path $file

$n = foreach ($obj in $xml.Objects.Object) {
$obj.Property | foreach -begin {
$h=@{}
} -process {
if ($_.property) {
#nested properties
$value = $_.property | Select Name,InnerText,Type
}
else {
$value = $_.InnerText
}
$h.add($_.name,$value)
} -end {
[pscustomobject]$h
}
} #foreach $obj
$n

This code enumerates the properties of each node and creates a hash table of each. In this version, everything is a string object, although the nested properties will indicate an object type. You can see my result in figure 4 for the operating system XML file.

[Click on image for larger view.] Figure 4.

If the XML file has a collection of objects, such as services, then $n will be a collection of converted service objects. All I need to do is modify the path of the XML file as I show in figure 5.

[Click on image for larger view.] Figure 5.

If all I'm doing is analyzing values, this might be all that I need. Of course, the easier way to recreate objects in PowerShell is to the cliXML cmdlets. But the concepts I've shown you here should work with any type of XML file, even those created outside of PowerShell. I'm not saying it will be easy but it can done.

Building such a tool is beyond the scope of what I can cover in this column. If you run into problems working with XML documents in PowerShell, I encourage you to use the forums at PowerShell.org. You might also keep an eye on my blog  as I'll post any XML-related tools I create on that site.

About the Author

Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, trainer and consultant. Jeff has written for numerous online sites and print publications, is a contributing editor at Petri.com, and a frequent speaker at technology conferences and user groups.

comments powered by Disqus
Most   Popular