Синтаксический анализ XML с помощью Scala: эквивалент «getElementByTagName (name)» в JS - PullRequest
4 голосов
/ 01 сентября 2011

Синтаксический анализ XML в Scala не кажется таким простым и понятным, как следовало бы.

Мне нужно было что-то похожее на document.getElementsByTagName (name) в JavaScript, но для моих целей все, что мне было нужно, это первый элемент определенного имени тега. Вот что я закончил:

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

Это в основном повторяется до тех пор, пока не будет найдено совпадение или все возможности не исчерпаны.

Теперь, когда функция, которая требовала, чтобы у меня была эта способность, была выпущена, я рассмотрел это немного больше, и это действительно беспокоит меня. Я уверен, что есть много библиотек Java, которые могут помочь разобрать XML, но, учитывая встроенную поддержку Scala для генерации XML (то есть она может быть просто встроена где угодно), мне любопытно, если я что-то упустил.

Есть ли лучший способ сделать это в Scala?

1 Ответ

6 голосов
/ 01 сентября 2011

Вы делаете это неправильно!
все, что мне было нужно, это первый элемент определенного имени тега
учитывая это xml:

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

Теперь вызов этого кода даст вам список всех узлов с данным именем тега:

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

Чтобы получить только первый:

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

P.S. Элемент deep-first будет рассматриваться как голова.

...