在scala中选择节点的所有子元素

Dan*_*itz 9 xml scala scala-xml

我想选择名为"a"的节点的第一个孩子Elem.我现在得到的是:

(xml \ "a")(0).child.collect {case e: Elem => e}
Run Code Online (Sandbox Code Playgroud)

这非常冗长.我在寻找类似的东西:

xml \ "a" \ "*"
Run Code Online (Sandbox Code Playgroud)

这可能在scala中吗?

Kev*_*ght 11

你不能对现有的\\\方法做任何事情NodeSeq.但是你可以使用一种新的\*方法扩展NodeSeq (注意缺少或空格字符),如pimp-your-library模式:

import xml.{NodeSeq, Elem}

class ChildSelectable(ns: NodeSeq) {
  def \* = ns flatMap { _ match {                                     
    case e:Elem => e.child                                   
    case _ => NodeSeq.Empty                                  
  } }
}

implicit def nodeSeqIsChildSelectable(xml: NodeSeq) = new ChildSelectable(xml)
Run Code Online (Sandbox Code Playgroud)

在REPL中,这给了我:

scala> val xml = <a><b><c>xxx</c></b></a>
xml: scala.xml.Elem = <a><b><c>xxx</c></b></a>

scala> xml \*                                                                            
res7: scala.xml.NodeSeq = NodeSeq(<b><c>xxx</c></b>)

scala> xml \ "b" \*
res8: scala.xml.NodeSeq = NodeSeq(<c>xxx</c>)

scala> xml \ "b" \ "c" \*
res9: scala.xml.NodeSeq = NodeSeq(xxx)
Run Code Online (Sandbox Code Playgroud)


Gui*_*ssé 5

这非常接近您所寻找的:

import scala.xml.Elem

val xml = <a><b><c>HI</c></b></a>

println( xml )
println( xml \ "_" )
println( xml \ "b" )
println( xml \ "b" \ "_" )
println( xml \ "b" \ "c" )
println( xml \ "b" \ "c" \ "_")


<a><b><c>HI</c></b></a>
<b><c>HI</c></b>
<b><c>HI</c></b>
<c>HI</c>
<c>HI</c>
// Empty
Run Code Online (Sandbox Code Playgroud)

  • 这比接受的答案更好。`"_"` 完全按照要求执行,无需编写新方法。需要维护的代码更少,让下一个查看代码的人感到困惑的非标准语法也更少。 (2认同)