To handle character data (the "b" in "<a>b</a>"), use characters:. But know it's sent multiple times for an element if its character data is separated by other markup like '<a>b<c/>d</a>' (the new comment explains this).
SAX parsing usually ends up needing a stack to track elements and their character data and is tedious but more efficient than DOM. You can't use XPath without DOM, but there's XMLParserStAX, a newer alternative to XMLPullParser that supports building partial DOM trees. Like XMLPullParser, it treats the document as a stream of event (StAX) objects you can "pull" from using a stream protocol (next, peek, atEnd, and others), but it also has messages like nextNode to construct a DOM tree out of the next event(s). You can use XPath on that.