April 1st, 2013

Working with XML

Doctor Scripto
Scripter

Summary: Windows PowerShell MVPs, Don Jones, Richard Siddaway, and Jeffrey Hicks share excerpts from their new book.

Microsoft Scripting Guy, Ed Wilson, is here. This week we will not have our usual PowerTip. Instead we have excerpts from seven books from Manning Press. In addition, each blog will have a special code for 50% off the book being excerpted that day. Remember that the code is valid only for the day the excerpt is posted. The coupon code is also valid for a second book from the Manning collection.

Today, the excerpt is from PowerShell in Depth
     By Don Jones, Richard Siddaway, and Jeffery Hicks

Photo of book cover

If you use Windows PowerShell, the Help, format, and type files are XML. The new “cmdlet over objects” functionality in Windows PowerShell 3.0 is based on XML. The HTML- and XML-related functionality hasn’t had any major changes in Windows PowerShell 3.0. In this excerpt from PowerShell in Depth, the authors cover several capabilities and provide some concise examples of how you might want to use them.

Windows PowerShell includes some great capabilities for working with two common forms of structured data: HTML and XML. Why is this important? Because HTML is a great way to produce professional-looking reports and you can use XML in so many places within your environment. The XML abilities in Windows PowerShell are no less amazing than its HTML abilities. We’ll cover a couple of specific use cases and the commands and techniques that help you accomplish each in this tip.

Using XML to persist data

One common use of XML is to preserve complex, hierarchical data in a simple, text-based format that’s easily transmitted across networks, copied as files, and so forth. XML’s other advantage is that it can be read by humans if required. Objects (PowerShell’s main form of command output), are one common kind of complex hierarchical data, and a pair of Windows PowerShell cmdlets can help convert objects to and from XML. This process is called serializing (converting objects to XML) and deserializing (converting XML back into objects). It’s almost exactly what happens in Windows PowerShell remoting when objects need to be transmitted over the network. Here’s a quick example: 

PS C:\> Get-Process | Export-Clixml proc_baseline.xml

This code creates a static, text-based representation of the processes currently running on the computer. The Export-Clixml cmdlet produces XML that’s specifically designed to be read back in by PowerShell.

Note   The Export verb, unlike the ConvertTo verb, combines the acts of converting the objects into another data format and writing them to a file.

PS C:\> Import-Clixml .\proc_baseline.xml | sort -property pm -Descending |

 select -first 10

 

Handles  NPM(K)    PM(K)     WS(K) VM(M)   CPU(s)     Id ProcessName

——-  ——    —–     —– —–   ——     — ———–

    783      77   336420    285772   819    43.69   2204 powershell

    544      41   196500    166980   652    13.41   2660 powershell

    348      24    91156     39032   600     1.28     92 wsmprovhost

    186      18    52024     35472   170     5.56    716 dwm

    329      28    24628     24844   213     0.30   2316 iexplore

    311      26    24276     22308   213     0.30    108 iexplore

    210      14    20628     26228    69     5.95   1828 WmiPrvSE

   1327      41    19608     33164   126    49.45    764 svchost

    398      15    19164     21120    56     3.95    728 svchost

    722      47    17992     23080  1394    13.45    924 svchost

The previous example demonstrates that the objects are imported from XML and placed, as objects, into the pipeline, where they can again be sorted, selected, filtered, and so forth. These deserialized objects are static, and their methods have been removed because they’re no longer “live” objects against which actions can be taken.

But because XML captures a hierarchy of object data, it’s an excellent tool for capturing complex objects. We recommend using the CliXML format as an intermediary rather than JSON.

Reading arbitrary XML data

You might also have a need to work with XML that comes from other sources. For example, the following is a brief XML file that contains information about two computers. You’ll use it in a running example:

<computers>

 <computer name=’WIN8′ />

 <computer name=’LOCALHOST’ />

</computers>

Warning   Unlike most of Windows PowerShell, XML tags are case sensitive. Using <computers> and </Computers> won’t work. Be careful if you’re retyping this example to get it exactly as shown here.

The Get-Content cmdlet can read the plain-text content of this XML file, but it will treat it as plain text. By casting the result as the special [xml] data type, you can force Windows PowerShell to parse the XML into a data structure. You’ll store the result in a variable to allow you to work with it and display the contents of the variable:

PS C:\> [xml]$xml = Get-Content .\inventory.xml

PS C:\> $xml 

computers

———

computers 

You can see that the variable contains the top-level XML element, the <computers> tag. That top-level element has become a property. Now you can start exploring the object hierarchy: 

PS C:\> $xml.computers

computer

——–

{WIN8, LOCALHOST}

PS C:\> $xml.computers.computer[0] 

name

—-

WIN8

PS C:\> $xml.computers.computer[1]

name

—-

LOCALHOST

You can see how it’s easy to explore the object model from this point.

Creating XML data and files

But reading XML data is only half the fun. Windows PowerShell also lets you create XML files that can be used outside of Windows PowerShell with the ConvertTo-XML cmdlet:

PS C:\> $xml=Get-WmiObject Win32_Volume | ConvertTo-Xml

PS C:\> $xml

 

xml                                     Objects

—                                     ——-

version=”1.0″                           Objects

PS C:\> $xml.objects.object[0]

 

Type                                    Property

—-                                    ——–

System.Management.ManagementObject      {PSComputerName, __GENUS, __CLAS…

PS C:\> $xml.GetType().Name

XmlDocument

You haven’t created an XML file, but only an XML representation of the Get-WmiObject result. But assuming you have XML experience and knowledge, you could explore or modify the XML document.

When you’re ready to save the XML document to a file, invoke the Save() method. You should specify the full path and filename:

PS C:\> $xml.Save(“c:\work\volume.xml”)

Unlike ConvertTo-HTML, you can’t pipe to Out-File and expect an XML document. You need to take this manual step, but you can use a shortcut like the following to do it all in one step:

(Get-WmiObject Win32_Volume | ConvertTo-Xml).Save(“c:\work\volume.xml”)

With so much of the world’s data in XML and HTML, being able to work those formats can be handy. Windows PowerShell provides a variety of capabilities that should be able to address most common situations. Obviously, the more knowledge you have of those formats and how they’re used, the more effective you’ll be with Windows PowerShell’s ability to handle them.

Here is the code for the discount offer today at www.manning.com: scriptw1
Valid for 50% off PowerShell in Depth and SQL Server DMVs in Action
Offer valid from April 1, 2013 12:01 AM until April 2 midnight  (EST)

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

Author

The "Scripting Guys" is a historical title passed from scripter to scripter. The current revision has morphed into our good friend Doctor Scripto who has been with us since the very beginning.

0 comments

Discussion are closed.