Search code examples
xmlscalascala-xml

Select all child elements of a node in scala


I want to select the first child Elem of a Node named "a". What I've got now is:

(xml \ "a")(0).child.collect {case e: Elem => e}

This is quite verbose. I was looking for something like:

xml \ "a" \ "*"

Is this possible in scala?


Solution

  • You can't do anything with the existing \ or \\ methods on NodeSeq. But you can extend NodeSeq with a new \* method (note the lack or space character), as per the pimp-your-library pattern:

    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)
    

    In the REPL, this then gives me:

    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)