The Scripting Wife Learns to Use PowerShell to Work with XML

The Scripting Wife Learns to Use PowerShell to Work with XML

  • Comments 10
  • Likes

Summary: In this blog, the Scripting Wife learns how to use Windows PowerShell to work with an XML file.

Microsoft Scripting Guy, Ed Wilson, is here. It is only eight days until the kickoff of the 2012 Scripting Games. Tomorrow the signup for the 2012 Scripting Games goes live. I have finished all the meetings, and everything is now in readiness state for the big event. I am sitting in the kitchen sipping a cup of English Breakfast tea, and looking over the chapter that I completed last night in my Windows PowerShell 3.0 Step by Step book. I close my eyes to think about one particular sentence when all of a sudden I feel a presence come into the room.

“If you are going to sleep, then you should get up from the table,” the Scripting Wife chided.

“I am not sleeping, I am deep in thought,” I replied.

“Then I am in deep trouble,” the Scripting Wife rejoined.

“What are you doing in here? The sun is still up,” I joked.

“Very funny. In fact, it is so funny I forgot to laugh,” she said. “Actually, since you are not doing anything, I need to you tell me about XML.”

“Say what?”

“XML. I need to know how to read an XML file,” she repeated.

“You are kidding.”

“Nope. I exported my book database, and it saved as an XML file. I need to know how to read it,” the Scripting Wife explained.

“OK. That makes sense. In Windows PowerShell, it is really easy. How do you read a plain text file?” I asked.

“I use the Get-Content cmdlet,” she said.

“It is the same thing, except that you use the letters XML inside square brackets. Open up Windows PowerShell on your computer, and then use Get-Content to read the XML file.”

The Scripting Wife stores her books.xml file in the FSO directory on her C:\ drive. Therefore, her command looks like this:

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

“Now look at what is contained in the $books variable,” I suggested.

The Scripting Wife typed the $books variable on its own line in the Windows PowerShell console. The command and its associated output are shown in the image that follows.

Image of command output

“Now look at the XML property,” I suggested.

The Scripting Wife typed the following command.

$books.xml

“OK. Now look at the BookInfo property.”

She typed the command that appears here.

$books.bookinfo.

The command to examine the XML property and the command to look at the BookInfo property are shown in the image that follows, along with the associated output.

Image of command output

“What is that booklist?” the Scripting Wife asked.

“I don’t know. Why don’t you access it and see.”

The Scripting Wife used the Up arrow to retrieve the previous command, and added BookList to the end of the command and pressed ENTER. Here is her command:

$books.bookinfo.booklist

“Well, it looks like a bunch of books,” she replied as she turned her monitor to me so I could see. The image that follows shows her Windows PowerShell console.

Image of command output

“Why don’t you keep going…But this time, pipe the output to More just in case you get all of your books rolling by,” I suggested.

The Scripting Wife once again used the Up arrow to retrieve her previous command, added Book to the end of the command, and piped the output to More. The command is shown here.

$books.bookinfo.booklist.book | more

Sure enough, after a few seconds, the book information began to scroll. The first little bit is shown here.

Image of command output

“Well that looks interesting, but how can I find more information about a book?” she asked.

“Why don’t you index into the collection? Choose the first book,” I suggested.

The Scripting Wife thought for a few seconds, and then she used the Up arrow to retrieve her previous command and then added the index operator. Her command is shown here.

$books.bookinfo.booklist.book[0]

The output from the previous command is shown here.

Image of command output

“You can use the same techniques to find information about the subjects of the book, and to find information about the title, plot, and other information.”

The Scripting Wife typed the commands that follow. As she examined the output from each command she continued to burrow deeper and deeper into the data structure of the first book.

$books.bookinfo.booklist.book[0].subjects

$books.bookinfo.booklist.book[0].subjects.subject

$books.bookinfo.booklist.book[0].mainsection

$books.bookinfo.booklist.book[0].mainsection.authors

$books.bookinfo.booklist.book[0].mainsection.authors.author

$books.bookinfo.booklist.book[0].mainsection.authors.author.person

Finally, she sat back and examined her handiwork. The output from these commands are shown in the image that follows.

Image of command output

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

 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Good info:

    ---books.xml ---

    msdn.microsoft.com/.../ms762271(v=vs.85).aspx

    $books=[xml](cat books.xml)

    $books.SelectNodes('//book[*]/title')

    This works like a charm. I can look up any attribute  quickly - BUT ...

    If the root looks like this: <catalog xmlns="www.test.org/.../">

    nothing is returned.

    Since most modern documents have one or more schemas and namespaces; how can we query nodes embedded in a namespace?

  • @jvr Why not use Select-Xml instead?

    Here is very nice movie that shows how to handle namespaces with it:

    www.youtube.com/watch

    So in your example: Select-Xml -Xml $books -XPath //Catalog:book[*]/Catalog:title -Namespace @{

    Catalog = 'http://www.test.org/.../' } | Select -Expand Node

    ... or something along those lines should do. ;)

  • @Bartek

    I was playing edvils advocate.  I see the issue of namespace come up everywhere but it is seldom described in any blog that refernces PowerShell.  

    There are videos and books on this.  It is a bit tricky for most users and most XML is hidden in a namespace or should be.

    I have numerous examples of XML with a dozen or more namespaces.

    I thought it might be a hint for Ed to blog on with.  I had not seen the Brundage videos.  Others here will be glad to have the link. Thanks.

    With [xml] we do it a bit differently by adding a namespace manager and using that to query.  The technique is pretty much the same in VBScript, jscript, java and others.  Select-Xml makes this easier for some things by hiding the complexity of doing this although you still need to know how to reference these in an XPath.

  • OK, you got me. :) I should probably expect it.

    And I agree: easy <root><branch></branch></root> examples are usually not really practical in the world full of namespaces and other elements, that those basics do not cover. But since this is Scripting Wife article its target is probably beginners, that may need only basic XMLs.

    Re: video - found it by accident today. Also glad I've found it, very handy IMO. :)

  • Hi Ed, Hi Teresa

    a very good intro into the world of XML!

    XML is a great standard for information exchange but we all should appreciate every tool that helps us to cope with it.

    Powershell has some support for XML and that's fine!

    We have to learn XPATH and we have to deal with namespaces anyway ... no way out, if you are diving deeper into business XML!

    @jrv and @Bartek: you know enough XML to be right and sure, there is never enough support for documents with many namespaces.

    This blog presents enough basic material for most average XML users, I suppose.

    I won't use Powershell in more complicated cases, I have specialized tools like the Altova Missionkit for that!

    It's good to have basic XML support in Powershell.

    Klaus

  • @Klaus - yes Altova is great.  I have become very adept at XPath with PosH XML. ONce you learn the namespace manager it is  very useful and quick.   Just extract.  I tend to use it for testing of queries before stuffing them into XSLT.  XSLT is better at format conversions than PowerShell.

    It is also useful when we are on systems with no VisualStudio/Altova/PrimalXML.

  • How would you iterate through every book in the booklist?

  • Great post

    I am a PS beginner. What if I want to use the info in the books.xml to create a directory hierachy on my (or any) disk?

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

    $DirectoryName = $books.bookinfo.booklist.book[0].mainsection.authors.author.person

    I guess I have the author stored in a variable with above and now I want to create a file directory with the name of the author:

    New-Item -Path C:\fso\Books -Name @DirectoryName

    Now I just want to run through the list of authors and create a directory for each.

    And later maybe create sub directories with names by subject. And finally I would grab the book files from the location referenced in books.xml

    How would that look like with PS and would it be better to script in a programming language?

    /Martin

  • Is there a way to get the contents of an xml file from an list of computers, like say from a csv?

  • Great Article Ed. :) Now, if you want to change the value of one of the parameters for example coverprice. Then how would you do it?