When Saxon is evaluating //a, it doesn't know that there is only one
a-element and that the a-element doesn't have any further a-elements in its
subtree - it has to keep looking!
I'm afraid I don't know why there aren't more calls on getStringValue() -
that will depend on the context in which the path expression appears.
Remember that an expression like //a/text() isn't naturally sorted, so in
general I would expect the text nodes to be retrieved first, and then sorted
into document order before being atomized. In your example the sort will be
a no-op, but that wouldn't be the case for example with
where the parent of rrr is in the result of //a ahead of the parent of qqq.
It might be that you have used the path expression in a context where order
doesn't matter, for example as an operand of "=", in which case Saxon will
be quite happy to retrieve the results in the "wrong" order.
I have to tell you that when I walk through the evaluation of such
expressions in the debugger, I often get surprises myself - sometimes it
seems the optimizer has a mind of its own.