Summary: Microsoft Scripting Guy, Ed Wilson, talks about calling XML document properties from within Windows PowerShell.
Microsoft Scripting Guy, Ed Wilson, is here. Craig Liebendorfer is back. No, he is not working on the Hey, Scripting Guy! Blog, but he is working on the Script Center as a whole. My old collaborator brings a lot to the table when it comes to bouncing ideas around, taking chances, and thinking outside the box. In fact, in our first recent meeting, we both came up with (about the same time) an idea for a new Script Center Home page. I think it looks really cool, let me know what you think.
By the way, each of the lines takes you to different places in the Script Center. We thought it was an appropriate way to navigate around the Script Center. Yep! The Windows PowerShell console. Here is an image of the new Home page:
Note This is the fourth in a series of posts about working with XML. You might also enjoy reading:
- Creating an XML Document for Admins
- Exploring XML Document by Using the [XML] Type Accelerator
- Using PowerShell to Explore Structure of XML Document
The first thing I do when I call XML document properties is read the XML file into a variable. Today I am going to call the variable XMLDocument to make the script easier to read. I use the [xml] type accelerator to cast the text into an XMLDocument object. The following image shows the document I am going to work with in XML Notepad:
When looking around at the properties that are available for working with XML documents, I like to use the MSDN reference for XMLDocument Class. I keep it open in Internet Explorer on one of my monitors so it will be available if I need it.
From looking at the document in XML Notepad, I can see that the root node is called Users, and that each child node is called User. Beneath that, I can find the UserName and the Address nodes. So how does this work in the Windows PowerShell console?
The first thing I do is read in the XML file, cast it to XMLDocument, and store it in a variable. This is shown here:
[xml]$xmldocument = Get-Content C:\fso\users.xml
I know the root node is called Users, and so I address it as shown here:
PS C:\> $xmldocument.Users
User
----
{User, User, User, User...}
I can see that the child nodes are called User, User, User... Therefore, I can simply call this from here:
PS C:\> $xmldocument.Users.User
ID UserName Address
-- -------- -------
0 UserName Address
0 UserName Address
0 UserName Address
0 UserName Address
0 UserName Address
But, I can also call the ChildNodes property. It returns the same thing, as shown here:
PS C:\> $xmldocument.Users.ChildNodes
ID UserName Address
-- -------- -------
0 UserName Address
0 UserName Address
0 UserName Address
0 UserName Address
0 UserName Address
I can always use ChildNodes to get child nodes in an XML document. For example, if I did not know that Users was at the root of the XML document, I could have used ChildNodes there. This technique is shown here:
$xmldocument.ChildNodes
The command and the output are shown here:
I see from the previous output, that the child nodes are named User. So I can gain access to them by calling them directly, as shown here:
PS C:\> $xmldocument.ChildNodes.user
ID UserName Address
-- -------- -------
0 UserName Address
0 UserName Address
0 UserName Address
0 UserName Address
0 UserName Address
But I also see in the previous image that the root is Users, and then I have User. So I can go back, change my command, and access them by name. This is shown here:
PS C:\> $xmldocument.users.user
ID UserName Address
-- -------- -------
0 UserName Address
0 UserName Address
0 UserName Address
0 UserName Address
0 UserName Address
But, because I know these are child nodes, I can also go back to my original script, and simply tack on ChildNodes, as shown here:
PS C:\> $xmldocument.ChildNodes.childnodes
ID UserName Address
-- -------- -------
0 UserName Address
0 UserName Address
0 UserName Address
0 UserName Address
0 UserName Address
What is cool about this approach is that even if I do not know what the nodes are called, I can still find the information. All three of these techniques and their associated output (which is the same in each case) are shown in the following image:
Whichever approach I decide to take, the technique is the same. I can address the first node by indexing into it. This is shown here:
PS C:\> $xmldocument.ChildNodes.childnodes[0]
ID UserName Address
-- -------- -------
0 UserName Address
I can now find the UserName information:
PS C:\> $xmldocument.ChildNodes.childnodes[0].UserName
FirstName LastName #text Password
--------- -------- ----- --------
Bob Smith BobSmith password
I use the same technique to get the Address information:
PS C:\> $xmldocument.ChildNodes.childnodes[0].Address
Street City State Zip
------ ---- ----- ---
123 main street anytown wa 1234567
But what if I did not know the names? Once again, I can use the more generic approach. Here is the FirstChild from the first child node. I can see that it is the same as UserName.
PS C:\> $xmldocument.ChildNodes.childnodes[0].FirstChild
FirstName LastName #text Password
--------- -------- ----- --------
Bob Smith BobSmith password
The LastChild gives me the address information. This is shown here:
PS C:\> $xmldocument.ChildNodes.childnodes[0].LastChild
Street City State Zip
------ ---- ----- ---
123 main street anytown wa 1234567
I can take this technique further, and address specific nodes or properties:
PS C:\> $xmldocument.Users.User.username
FirstName LastName #text Password
--------- -------- ----- --------
Bob Smith BobSmith password
Bob Smith BobSmith password
Bob Smith BobSmith password
Bob Smith BobSmith password
Bob Smith BobSmith password
PS C:\> $xmldocument.Users.User.username.LastName
Smith
Smith
Smith
Smith
Smith
That is all there is to using some of the XMLDocument properties. XML Week will continue tomorrow when I will talk about more cool stuff.
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