Here's what I'm going to go with:

def parse(response: NodeSeq):Either[String, String] = {
    response \\ "user" match {
        case ns if !ns.isEmpty => Right(ns.text)
        case ns => response \\ "authenticationFailure" match {
            case ns if !ns.isEmpty => 
                val code = ns \ "@code"
                val msg = ns.text.trim
                Left(s"Failure: ${code} ${msg}")
            case ns => Left("Unexpected response from CAS: " + response.toString)

It uses \ to search through the tree rather than \ that my original solution used (that same technique could also simplify my original solution). It also uses a match statement, obviously. I think the match statement makes the result more readable and easier to develop than the original solution. But maybe I'm just showing my imperative roots!

More Query from same tag