I have been reflecting alot lately, however I was actually tipped off to this one via Lamont Harrington. Since it was news to me (and I'm typically not the slowest fish in the barrel), I find it worth mentioning:

Decompile the XmlNode.SelectSingleNode method and you will get the following (Excuse my VB.NET):

Public Overloads Function SelectSingleNode(ByVal xpath As String) As XmlNode
Begin Function

Dim list1 As XmlNodeList
Dim node1 As XmlNode
Try
list1 = Me.SelectNodes(xpath)
node1 = list1.ItemOf(0)
Catch ArgumentOutOfRangeException
node1 = Nothing
End Try
Return
node1

End Function

You can see that SelectSingleNode just wraps SelectNodes, which means it is (at best) no faster than SelectNodes. Also, if you follow the trail a bit further, the decompilation of SelectNodes is:

Public Overloads Function SelectNodes(ByVal xpath As String) As XmlNodeList
Begin Function

Dim navigator1 As XPathNavigator
navigator1 = Me.CreateNavigator
Return New XPathNodeList(navigator1.Select(xpath))
End Function

This is the painful part - Each call to SelectNodes is actually creating a new XPathNavigator instance. 

I guess the preferred solution is to instantiate my own XPathNavigator and reuse that for executing any and all XPath queries on the document, especially when the queries sit inside nested loops...

Update 4/26/2004:  This post is still recieving a steady 100+ hits a day, so I just thought y'all might like to know where to go from here. For a good summary of what's new in this area (selecting nodes using XPath based readers/navigators), read this post by Dare.