Calling XMLDocument Methods in PowerShell

Doctor Scripto

Summary: Microsoft Scripting Guy, Ed Wilson, talks about calling XMLDocument methods in Windows PowerShell.

Microsoft Scripting Guy, Ed Wilson, is here. Today is Friday the 13th. Cool. Luckily, I do not have to go anywhere tonight around midnight, by the light of a full moon. But I am going to use Windows PowerShell methods to slice and dice some XML. Luckily, this is a very neat technique, and it will not leave any wayward bits of data laying around. Besides, I am listening to Scripting Cmdlet Style, and that should scare off anything that is non-PowerShell related.

    Note  This is the fifth in a series of posts about working with XML. You might also enjoy reading:

Although Windows PowerShell makes it easy to navigate XML documents, at times (because of the size of the files, the numbers of nodes, or some other non-PowerShell related element), one may want to drop down to the .NET Framework to do some work.

To make things a bit more interesting today, I decided to use an XML document from MSDN called Sample XML File (books.xml). All one needs to do to use it is to copy the code from the MSDN page, paste it into a plain Notepad text file, and rename the file Books.xml. After I have done that, I open it in XML Notepad for fun. This is what I find:

Image of menu

One of my favorite XMLDocument methods is the SelectNodes method. It will accept an XPATH path, which is simply a specially formatted string. The easiest XPATH query to use is “*”, which means, “Dude, show me everything.”

In the following example, I first read in the XML by using Get-Content and the [XML] type accelerator. I then use the ChildNodes property and the SelectNodes method.

[xml]$xmldocument = Get-Content C:\fso\books.xml

$xmldocument.ChildNodes.selectNodes(“*”)

The commands and the associated output from the commands is shown here:

Image of command output

Because I see that my query with the wildcard character (“*”) worked as I thought it would, I decide to get brave and return only the titles. I do this by using the forward slash ( / **) symbol as the separator, and I simply call the **Title node that I saw in the output from my first query. The query is shown here:

$xmldocument.ChildNodes.selectNodes(“*/title”)

The following image shows the query and the associated output:

Image of command output

I can also pick up the Genre of the books, as shown here:

$xmldocument.ChildNodes.selectNodes(“*/genre”)

The command and associated output are shown here:

Image of command output

The list of genres looks cool, but I really only want to know what genres are represented—that is, I want a unique list. Because this is Windows PowerShell, I can easily find this information in a couple of ways. The way I like to do this is to use Select-Object and specify the –Unique switch:

$xmldocument.ChildNodes.selectNodes(“*/genre”) | select ‘#text’ –Unique

The output is nice, and it lets me know only the genres that are unique in the list:

Image of command output

Maybe I want to know the value of all of my books, and how many books I actually have. This is easy to do with Windows PowerShell, XML, and XPath. Here is the command I use:

$xmldocument.ChildNodes.SelectNodes(“*/price”) | measure ‘#text’ –Sum

Here is the command and the output from the command:

Image of command output

Now I want to add one of my books to the Books.xml file. To do this, I will first clone one of the book nodes, as shown here:

$copy = $xmldocument.catalog.book[0].Clone()

Now, I simply assign new values for each of the properties. This appears here:

$copy.id = ‘bk113’

$copy.author = ‘Wilson, Ed’

$copy.title = ‘Windows PowerShell Best Practices’

$copy.price = ‘59.99’

$copy.publish_date = ‘2014-01-25’

$copy.description = ‘Automate system administration using Windows PowerShell best practices’

Now, I want to add the new node to the XML. I do this by calling the appendchild method and passing the $copy. This appears here:

$xmldocument.catalog.appendchild($copy)

I can now check the child nodes to ensure that it is added:

$xmldocument.ChildNodes.childnodes

Now I write the InnerXML to a text file with the XML extension:

$xmldocument.InnerXml >>c:\fso\modified.xml

I can now open it in XML Notepad to see if it worked properly. Here is my output:

Image of menu

That is all there is to using XML methods. Join me tomorrow for the Weekend Scripter when I will talk about non-PowerShell books for Windows PowerShell people.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

0 comments

Discussion is closed.

Feedback usabilla icon