XPath can be used to navigate or search an XML document. PowerShell (and .NET) uses XPath 1.0.
The structure and format of XPath queries are beyond the scope of this chapter. However, a number of web resources are available, including:
https://msdn.microsoft.com/en-us/library/ms256115(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/ms256115(v=vs.110).aspx
Terms and values used in XPath queries, and XML in general, are casesensitive.
Given the following XML snippet, Select-Xml might use an XPath expression to select the engines of green cars:
$string = @" <?xml version="1.0"?> <cars> <car type="Saloon"> <colour>Green</colour> <doors>4</doors> <transmission>Automatic</transmission> <engine> <size>2.0</size> <cylinders>4</cylinders> </engine> </car> </cars> "@
The XPath expression and the result are shown here:
PS>Select-Xml -XPath '//car[colour="Green"]/engine' -Content $string | Select-Object -ExpandProperty Node size cylinders ---- --------- 2.0 4
A similar result can be achieved using the SelectNodes method of an XML document:
([Xml]$string).SelectNodes('//car[colour="Green"]/engine')
Select-Xml has an advantage in that it can be used to work against files directly using the Path parameter:
SelectNodes and XPathNodeList:
If the SelectNodes method is called, and there are no results, an empty XPathNodeList object is returned. The following condition is flawed:
$nodes = $xml.SelectNodes('//car[colour="Blue"]')
if ($nodes) {
Write-Host "A blue car record exists"
}
In this case, using the Count property is a better approach:
if ($nodes.Count -gt 1) {
Write-Host "A blue car record exists"
}
If the search is only concerned with the first matching entry, or the search always returns a unique result, the SelectSingleNode method can be used instead.
If the SelectNodes method is called, and there are no results, an empty XPathNodeList object is returned. The following condition is flawed:
$nodes = $xml.SelectNodes('//car[colour="Blue"]')
if ($nodes) {
Write-Host "A blue car record exists"
}
In this case, using the Count property is a better approach:
if ($nodes.Count -gt 1) {
Write-Host "A blue car record exists"
}
If the search is only concerned with the first matching entry, or the search always returns a unique result, the SelectSingleNode method can be used instead.