我在Scala工作,需要区分代表成功或失败的XML消息。我发现的信息为拆开已知的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'>
'service' and 'ticket' parameters are both required
</cas:authenticationFailure>
</cas:serviceResponse>""")
下面的代码做了我想要的(我最终将返回一个案例类,但这对于播放来说很好......):
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 :(得分: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)
}
}
}
它使用\来搜索树而不是我使用的原始解决方案(同样的技术也可以简化我的原始解决方案)。显然,它也使用匹配语句。我认为匹配语句使结果比原始解决方案更易读,更容易开发。但也许我只是在展示我的命令根源!