I like retronym's drop(n).headOption pattern as it accounts for when you have less children than n. But I think you meant the second child node (excluding text nodes), not the second instance of the <foo> tag. With that in mind, combining with your answer or using partialMap:
node.child.partialMap{case x:scala.xml.Elem => x}.drop(n).headOption
node.child.filter(_.isInstanceOf[scala.xml.Elem]).drop(n).headOption
This has to assume that you won't want to extract text in:
val node = <something><foo/>text</something>
Efficiency wise, the only other thing I could think of is to make filter lazy if you wanted to retrieve the second child when there are a large number of children. I think this may be achieved by running filter on node.child.iterator instead.
Edit:
Changed toIterable to iterator.
good point, calling drop(n) on an ArrayBuffer will cause additional allocations, also how many is hard to tell, since it seems drop is overridden in IndexSeqLike. But using the iterator would address that too. So for large number of children:
node.child.iterator.filter(_.isInstanceOf[scala.xml.Elem]).drop(n).next
If you want to have it be safe, you may need to define a function to check for hasNext.
All of this is tested only in 2.8.