2014-10-08 89 views
1

我在Scala中工作,需要區分代表成功或失敗的XML消息。我發現的信息提供了很多關於拆開已知XML片段的信息,但不能確定您擁有哪個片段。解析Scala中的替代XML文字

下面是兩種可能的消息:

val success = XML.loadString("""<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'> 
       <cas:authenticationSuccess> 
        <cas:user>bwbecker</cas:user> 
       </cas:authenticationSuccess> 
       </cas:serviceResponse>""") 

val failure = XML.loadString("""<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'> 
       <cas:authenticationFailure code='INVALID_REQUEST'> 
        &#039;service&#039; and &#039;ticket&#039; parameters are both required 
       </cas:authenticationFailure> 
       </cas:serviceResponse>""") 

下面的代碼我想要做什麼(我最終會回到case類的不是,但是這是好的播放...):

def parse(response: NodeSeq):Either[String, String] = { 

(response \ "authenticationSuccess").headOption 
    .flatMap(succ => (succ \ "user").headOption) 
    .map(usr => Right(usr.text)) 
    .getOrElse((response \ "authenticationFailure").headOption 
    .map{fail => 
     val code = fail \ "@code" 
     val msg = fail.text 
     Left(s"Failure: ${code} ${msg}") 
    } 
    .getOrElse(Left("Really Botched")) 
) 
} 

但是,我覺得這很難編碼和閱讀。有沒有更好的辦法?如果我有五種不同的信息可以區分呢?

我嘗試了匹配器,但對XML的神祕語法感到氣餒(cas:命名空間似乎使事情變得複雜)。

任何改進我的代碼的指導?

回答

0

這裏就是我要去用:

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) 
     } 
    } 
} 

它使用\在樹中尋找,而不是\所用我原來的解決方案(即相同的技術也可以簡化我原來的解決方案)。它顯然也使用了匹配語句。我認爲匹配語句使得結果比原始解決方案更易讀易懂。但也許我只是展示了我的迫切根源!

+0

你真的需要返回一個Either []嗎?如果是我,我會返回一個選項[字符串]如果驗證,否則無。 – Falmarri 2014-10-08 23:33:00

+0

是的,好點。謝謝。 – bwbecker 2014-12-07 13:57:52