Question

XML parsing in Scala doesn't seem to be as easy and straightforward as it should be.

What I needed was something that behaved similar to document.getElementsByTagName(name) in JavaScript, but for my purposes all I needed was the first element of a particular tag-name. Here is what I ended up with:

import scala.xml.{Document, Elem, Node}
import scala.xml.parsing.ConstructingParser
def _getFirstMatchingElementByName(search: String, n: Node): Option[Node] = {
    if (n.label == search) {
        Some(n)
    } else {
        var i = 0
        var result: Option[Node] = None
        try {
            while (result == None) {
                result = _getFirstMatchingElementByName(search, n.child(i))
                i += 1
            }
        } catch {
            case e: IndexOutOfBoundsException => None
        }
        result
    }
}

It basically recurses through until a match is found or all possibilities are exhausted.

Now that the feature which required that I have this ability has been released I have reviewed this a little more and it really bugs me. I'm sure there are many Java libraries available to help parse XML, but given the native support that Scala has for generating XML (i.e. it can pretty much just be inlined anywhere), I am curious if I am missing something.

Is there a better way to do this in Scala?

Was it helpful?

Solution

You doing it wrong!
all I needed was the first element of a particular tag-name
given this xml:

val page = 
  <root>
    <need>text1</need>
    <doesnotneed>text2</doesnotneed>
    <doesnotneed>text3</doesnotneed>
    <need>text4</need>
  </root>

Now calling this code will give you list of all nodes with given tag name:

scala> page \\ "need"
res3: scala.xml.NodeSeq = NodeSeq(<need>text1</need>, <need>text4</need>)

To get only first one:

scala> page \\ "need" head
res4: scala.xml.Node = <need>text1</need>

P.S. deep-first element would be treated as head.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top