Powershell and XML

Introduction

XML is everywhere. As a result, many of us find the need to work with XML and traditional text editors don't cut it. Some editors provide decent formatting (like Notepad++), but they don't provide a mechanism to examine the underlying data in the XML programmatically.

PowerShell makes handling XML very simple. It converts XML elements to properties on .NET objects without the need to write any parsing code. So all you need is PowerShell installed on your machine and you're ready to go!

A Quick Example

Here's a quick example to show how PowerShell maps the XML elements and attributes to object properties. It assumes the file.xml file exists and contains the text below:

<!-- file.xml -->
<employees>
    <employee id="101">
        <name>Frankie Johnny</name>
        <age>36</age>
    </employee>
    <employee id="102">
        <name>Elvis Presley</name>
        <age>79</age>
    </employee>
    <employee id="301">
        <name>Ella Fitzgerald</name>
        <age>102</age>
    </employee>
</employees>

Examples of loading file.xml into an XmlDocument object and getting at the nodes/properties.

 1 PS C:\> $xml = [xml](get-content file.xml)
 2 PS C:\> $xml
 3 
 4 #comment                                                    employees
 5 --------                                                    ---------
 6  file.xml                                                   employees
 7 
 8 PS C:\> $xml.employees
 9 
10 employee
11 --------
12 {Frankie Johnny, Elvis Presley, Ella Fitzgerald}
13 
14 PS C:\> $xml.employees.employee
15 
16 id                                      name                                    age
17 --                                      ----                                    ---
18 101                                     Frankie Johnny                          36
19 102                                     Elvis Presley                           79
20 301                                     Ella Fitzgerald                         102
21 
22 PS C:\> $xml.employees.employee[0].name
23 Frankie Johnny
24 PS C:\> $xml.employees.employee[1].age
25 79
26 PS C:\>

The cmdlet get-content is equivalent to cat in UNIX and returns the contents of the file as lines of text.

The square brackets '[xml]' in front of the get-content cmdlet indicate an type object. In this case, it is casting the text returned from get-content file.xml to an XmlDocument object. Once you have an XmlDocument object, PowerShell's builtin support for XML kicks in. The individual XMLElement objects present their children nodes as properties. This means the element name is the property. In this case, the root element is <employees> so it is accessed as a property on the $xml variable. And try this: type '$xml.em' and then hit TAB. That's right, tab completion of the element names. Makes it a little easier for ya.

But Wait, There's More

You still have access to the methods of the underlying XmlElement object too. Execute the command '$xml | gm' to get a list of all the methods and properties available for any XML node. Which means you can use SelectNodes() and SelectSingleNode() using the XPath query syntax. Here's an example using the SelectNodes() method on XmlElement.

1 PS C:\> $xml = (Get-Content file.xml)
2 PS C:\> $xml = [xml](Get-Content file.xml)
3 PS C:\> $xml.SelectNodes("/employees/employee")
4 
5 id                                      name                                    age
6 --                                      ----                                    ---
7 101                                     Frankie Johnny                          36
8 102                                     Elvis Presley                           79
9 301                                     Ella Fitzgerald                         102

And by passing those results through the PowerShell pipeline, you can pipe those results into other commands like select-object, where-object and foreach-object to prune the values or execute commands based on the values for a very expressive and powerful scripting experience. Note: I'm using the alias for get-content (gc). Most PowerShell cmdlets have aliases that are an acronym from their fullname.

In the 4 examples below, we use where-object and foreach-object to check properties of the employee nodes so we only return those that match a certain criteria or manipulate them in some way. The first example looks like it should return the 2 employees with age over 50 but it doesn't. The reason is that the properties of the XML objects are always strings. Thus it does a lexicographical comparison. That is easily solved by casting the value to an int using the type cast operator [int] much in the same way we cast the string output of get-content to an xml document [xml].

The 2nd command shows that casting to an int properly returns the employees older than 50. The 3rd example shows that you can call the methods on the string objects returned. So let's say the first digit of your employee id indicates a department, you can easily use the startsWith() method on the String object. What is $_? The '$_' is a variable that represents the current pipeline object. It is used to so that you can manipulate the current object being passed to your function/script block. The where-object cmdlet takes a script block (denoted by the curly brackets { }) and executes the powershell script inside. If the expression evaluates to true, the object is passed down the pipeline to the next command (which in this case is the default output command) and when the where-object script block evaluates to false, the object is "dropped".

If you wanted to manipulate the XML nodes values somehow you would use foreach-object which also takes a script block. And in fact the 4th command uses foreach to create some concatenated string of all the employee nodes values.

 1 PS C:\> $xml = [xml](gc file.xml)
 2 PS C:\> $xml.employees.employee | where { $_.age -gt 50 }
 3 
 4 id                                      name                                    age
 5 --                                      ----                                    ---
 6 102                                     Elvis Presley                           79
 7 
 8 PS C:\> $xml.employees.employee | where { [int]$_.age -gt 50 }
 9 
10 id                                      name                                    age
11 --                                      ----                                    ---
12 102                                     Elvis Presley                           79
13 301                                     Ella Fitzgerald                         102
14 
15 PS C:\> $xml.employees.employee | where { $_.id.startsWith("1") }
16 
17 id                                      name                                    age
18 --                                      ----                                    ---
19 101                                     Frankie Johnny                          36
20 102                                     Elvis Presley                           79
21 
22 PS C:\> $xml.employees.employee | foreach { $_.id + ":" + $_.name + ":" + $_.age }
23 101:Frankie Johnny:36
24 102:Elvis Presley:79
25 301:Ella Fitzgerald:102

 

 

转载于:https://www.cnblogs.com/alexzp/archive/2012/10/19/2730910.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值