Navigating XML Files with PowerShell (Using the Help File as an example)

In the blog post called, Reading in the Help File with Get-Content (Part 2 of 2), I started the process of roaming around the PowerShell help file.

I followed the process I'm going to talk through when I needed to build some quick scripts that checked all of our Windows Server help files to make sure we had completely filled out the required fields. But before I could write scripts to automate the file verification, I first needed to know what I was looking to verify.  So, in a sense, I’m more crawling through the file, than walking.

What Am I Looking For?

I can see the skeleton of the information I want from the help file when I run, get-help get-help –full and distill the titles of the sections. (I could have used any cmdlet to see the section headers, so generalized it would be get-help <cmdlet name> -full

NAME

SYNOPSIS

SYNTAX   

DESCRIPTION   

PARAMETERS

INPUTS

OUTPUTS 

NOTES

     -------------------------- EXAMPLE 1 -------------------------- 

                              

        -------------------------- EXAMPLE 15 --------------------------

RELATED LINKS

Rereading the PowerShell Help File (recap from last blog post)

In the past blog post, I had made it down to the level where I could see an element known as command. I've repeated the two sets of commands here so we can get started together (I’ve highlighted the two lines of commands I typed in):

PS C:\> $help_xml = [xml] (Get-Content $pshome\en-us\System.Management.Automation.dll-Help.xml)

PS C:\> $help_xml.helpItems | gm -MemberType properties

   TypeName: System.Xml.XmlElement

Name         MemberType Definition
----         ---------- ----------
#comment     Property   System.Object[] #comment {get;}
command      Property   System.Object[] command {get;}
providerHelp Property   System.Object[] providerHelp {get;}
schema       Property   System.String schema {get;set;}

Let’s go down one level to see what child nodes are inside the command XML node: (How did I know to look at the command node? Well, I want to see information for cmdlet help. This pretty much rules out the other three nodes based on their names.)

PS C:\> $help_xml.helpItems.command | gm -MemberType properties

   TypeName: System.Xml.XmlElement#https://schemas.microsoft.com/maml/dev/command/2004/10#command

Name                 MemberType Definition
----                 ---------- ----------
#comment             Property   System.Object[] #comment {get;}
alertSet             Property   System.Xml.XmlElement alertSet {get;}
command              Property   System.String command {get;set;}
description          Property   System.Xml.XmlElement description {get;}
details              Property   System.Xml.XmlElement details {get;}
dev                  Property   System.String dev {get;set;}
examples             Property   System.Xml.XmlElement examples {get;}
inputTypes           Property   System.Xml.XmlElement inputTypes {get;}
maml                 Property   System.String maml {get;set;}
nonTerminatingErrors Property   System.String nonTerminatingErrors {get;set;}
parameters           Property   System.Xml.XmlElement parameters {get;}
relatedLinks         Property   System.Xml.XmlElement relatedLinks {get;}
returnValues         Property   System.Xml.XmlElement returnValues {get;}
syntax               Property   System.Xml.XmlElement syntax {get;}
terminatingErrors    Property   System.String terminatingErrors {get;set;}

So, it looks like $help_xml.helpItems.command contains the cmdlet help topics I'm interested in. Some of the element/property names correspond to the section titles I’m looking for: description, examples, syntax, parameters, relatedLinks. Others seem close: inputTypes and returnValues. I don’t see notes, but there is an element called details, which might have more information.

Instead of looking at the properties of the $help_xml.helpItems.command members, let’s look at what happens when I just type $help_xml.helpItems.command and press enter from the PowerShell command line:

PS C:\> $help_xml.helpItems.command

maml                 : https://schemas.microsoft.com/maml/2004/10
command              : https://schemas.microsoft.com/maml/dev/command/2004/10
dev                  : https://schemas.microsoft.com/maml/dev/2004/10
details              : details
description          : description
#comment             : { Cmdlet syntax section,  Cmdlet parameter section  ,  Input - Output section,  Error section...
                       }
syntax               : syntax
parameters           : parameters
inputTypes           : inputTypes
returnValues         : returnValues
terminatingErrors    :
nonTerminatingErrors :
alertSet             : alertSet
examples             : examples
relatedLinks         : relatedLinks

I’ve only displayed the first command that is spewed when you type $help_xml.helpItems.command. What you’ll see if you try this for yourself is a spew of listings that all appear the same – no actual information, though. Because we’re seeing multiple copies, I suspect that command is actually an array. Let’s look at the first element of command details.

PS C:\> $help_xml.helpItems.command[0].details

name        :
                                 Add-History

description : description
copyright   : copyright
verb        : Add
noun        : History
version     :

Woo hoo! OK, we’ve hit pay dirt here. Here is the name (Add-History) along with more elements providing verb (Add) and noun (History). And if we want to display just the name of the cmdlet we can run:

PS C:\> $help_xml.helpItems.command[0].details.name

                   Add-History

But maybe we want to look at a different command, maybe the 100th command in the file. If we do this here’s what we see:

PS C:\> $help_xml.helpItems.command[100].details
PS C:\>

Not very enlightening, but unless we specifically setup to trap an error, we might not see one. I’m guessing we might have put in too large an index for the array of $help_xml.helpItems.command We can find length of the array (number of cmdlets that have help specified in this file) by running:

PS C:\> $help_xml.helpItems.command.length
42

Because PowerShell arrays are zero indexed, the maximum index is length - 1. In this case, if we keep the index to ((length=42) - 1) = 41 and under, we’ll get a result. For the index 41,

PS C:\> $help_xml.helpItems.command[41].details

name        :
                                 Where-Object

description : description
copyright   : copyright
verb        : Where
noun        : Object
version     :

Let’s go a little further and see what’s under description:

PS C:\> $help_xml.helpItems.command[41].details.description

para
----
Creates a filter that controls which objects will be passed along a command pipeline.

Comparing to the results from Get-Help Where-Object –full, this looks like what we’ve been seeing as the synopsis. That means we can get the short description or synopsis text directly with the dotted notation with para at the end:

PS C:\> $help_xml.helpItems.command[41].details.description.para
Creates a filter that controls which objects will be passed along a command pipeline.

To Recap What We’ve Found in the PowerShell Help File So Far

Steps Command
Read in XML file as XML $help_xml = [xml] (Get-Content $pshome\en-us\System.Management.Automation.dll-Help.xml)
Find out how many cmdlets we have help for in file $help_xml.helpItems.command.length
Print out name of cmdlet N, where N is the index into the command array $help_xml.helpItems.command[N].details.name
Print out short description or synopsis of cmdlet N, where N is the index into command array $help_xml.helpItems.command[N].details.description.para

We’re still looking for syntax, full description, parameters with description, inputs, outputs, notes, examples, and related links. Feel free to look around for these on your own. I will be continuing to hunt down more information within the PowerShell help file in the next blog post.

And again, let me know what other XML files you think we should walk through as an exercise when we’re done with this file. Feel free to post suggestions in the comment sections of this post. Looking to hear from you soon. -- Judith