Lazy Diary @ Hatena Blog

PowerShell / Java / miscellaneous things about software development, Tips & Gochas. CC BY-SA 4.0/Apache License 2.0

XmlNode.SelectNodes() always returns List in PowerShell 2.0

Problem:

In PowerShell, by using XML DOM API in .NET, you can access to a child element in XML as a ordinary property.

PS > $xml = New-Object System.Xml.XmlDocument
PS > $xml.LoadXml('<a><b id="1">foo</b></a>')
PS > $xml.SelectNodes('//a').b

id                                                            #text
--                                                            -----
1                                                             foo

But in PowerShell 2.0, the same script returns nothing ($null).

PS > $xml = New-Object System.Xml.XmlDocument
PS > $xml.LoadXml('<a><b id="1">foo</b></a>')
PS > $xml.SelectNodes('//a').b

Reason:

It seems to be by design, or caused by some unintentional change in implementation of PowerShell.

  • In PowerShell 4.0 or later, the result of SelectNodes() will be XmlElement if there is only one element in the result.
  • In PowerShell 2.0, the result of SelectNodes() will be always an list of XmlElement.

Solution:

You should always get child nodes through ForEach-Object. The script below does not return $null in PowerShell 2.0 and 4.0 or later.

PS > $xml = New-Object System.Xml.XmlDocument
PS > $xml.LoadXml('<a><b id="1">foo</b></a>')
PS > $xml.SelectNodes('//a') | ForEach-Object { $_ }

b
-
b