Skip Navigation LinksHome > View Post

Powershell to test your XPath

I'm quickly coming to the realisation that Powershell might just replace all those little 'trial and error' apps that I used to download everytime I needed one. Not too long ago I posted about how PowerShell had become my weapon of choice when playing with Regular Expressions. Earlier today a colleague contacted me for some help with an XPath query. Sure enough, powershell would have been more than up to the task.

We start by creating an XML document to play with:

$xml = [xml] '<root><node att="a">hello</node><node att="b">goodbye</node></root>'

How easy was that? And now we can

$xml.SelectNodes("/root/node")

att #text
--- -----
a hello
b goodbye

or test your predicates

$xml.SelectNodes("/root/node[@att='a']")

att #text
--- -----
a hello

I won't bore you with a million examples suffice to say you have a full XmlDocument (from System.Xml) in $xml at your disposal.

Want to load a meatier xml document from disk for your experimentation?

$xml = New-Object "System.Xml.XmlDocument"
$xml.load("c:\myfile.xml")

Very handy. If only PowerShell shipped as part of Vista... get yours here.

Tags: Powershell

 
Josh Post By Josh Twist
4:35 AM
26 Jan 2008

» Next Post: Using the Source Code Editor for XAML in Visual Studio
« Previous Post: New in WPF 3.5: 2. Support for IDataErrorInfo

Comments are closed for this post.

Posted by Phil Fearon @ 27 Jan 2008 10:05 AM
XPath. A great way for extracting xml config data stored as xml for a powershell script. A couple of points -

A single-line alternative to:

$xml = New-Object "System.Xml.XmlDocument"
$xml.load("c:\myfile.xml")

would be:

$xml = [xml] (get-content "c:\myfile.xml")

Also, one thing that threw me at first was that the returned XmlNode(s) is 'wrapped' by PowerShell. So, to access basic properties of XmlNode, I had to use the 'PSBase' member as in:

$value = $node.psbase.innertext


Posted by Josh @ 02 Dec 2008 7:35 AM
Cheers Phil,

Nice improvement using get-content. The alternative to using psbase is to use the getter method directly, e.g.:

$node.get_InnerText()

Josh

Posted by Jeff @ 26 Jan 2009 5:37 PM
No Joke Phil, I just found out about the PSBase concept from reading this article and I was getting quite frustrated trying to use .Value and .InnerText and such until I just couldn't take it any more and stated googling.

Posted by RobLundkvist @ 31 Mar 2009 3:35 AM
I ran into the psbase issue as well, thanks :)

Posted by Dima @ 31 Aug 2010 5:27 PM
Just wish to give couple more examples.

read file another format;
[xml] $foo = gc c:\temp\blah.xml


Setting values using xpath wilds:
$xpath = "//*[@name='nameOfNode']/value"
$foo.SelectSingleNode($xpath).set_InnerText("BLAH")

much more readable the hash aproache:
[xml] $foo = "<?xml version='1.0'?><authorization><allow roles='myDomain\Domain Users' /><deny users='*' /></authorization>"

$foo.authorization.allow.roles = "new\Domain Users"

keep one thing in mind, new value will have to be a string, it does not do well with anything else... so convert to string first

Finally, biggest pain is the Namespaces, you can spend hours researching it.

In Hibernate i see:
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">

you have to create a new namespace object:

$ns = New-Object Xml.XmlNamespaceManager $foo.NameTable
$ns.AddNamespace( "nh", "urn:nhibernate-configuration-2.2" )
$xpath = "//nh:property[@name='connection.connection_string']"
$node = $xml.SelectSingleNode($xpath, $ns)

good luck with the last one

Posted by Hartmut @ 17 Aug 2011 9:45 AM
This threat was very helpful for me. But still I'm in trouble with the namespace stuff.
$ns = New-Object Xml.XmlNamespaceManager $foo.NameTable
For what stands the variable $foo.NameTable?

Thanks
Hartmut

© 2005 - 2014 Josh Twist - All Rights Reserved.