Соберите пути от узла - PullRequest
       10

Соберите пути от узла

0 голосов
/ 07 января 2011

Я хочу собрать набор путей из xml.Node.У меня есть рабочий код, но это некрасиво.Мне нужна помощь, чтобы очистить его (или, возможно, лучшее решение?)

import xml._

def paths(node: Node): Set[String] = {
  def inner(base: String, node: Node): Set[String] = {
    if (node.isInstanceOf[Elem]) {
      val newBase = "%s/%s".format(base, node.label)
      val selfAndChildren = node.child.flatMap(
        inner(newBase, _)).toSet.asInstanceOf[Set[String]] + newBase
      val attributes = node.attributes.map(a => 
        "%s/@%s".format(newBase, a.key)).toSet.asInstanceOf[Set[String]]
      selfAndChildren ++ attributes
    } else Set.empty[String]
  }
  inner("", node)
}

Использование:

scala> val x = <a><b z="true"><c>3</c></b></a>
x: scala.xml.Elem = <a><b z="true"><c>3</c></b></a>

scala> paths(x)                               
res1: Set[String] = Set(/a/b/c, /a/b, /a/b/@z, /a)

Что мне не нравится:

  • Система типов вынудила меня привести результаты toSet
  • Я ожидал, что что-то в XML API получит полный путь любого Element
  • Не знаюЯ не хотел использовать проверку isInstanceOf[T], но не смог заставить работать сопоставление с образцом.
  • Это слишком многословно.

1 Ответ

2 голосов
/ 07 января 2011

Чисто глядя на стиль, а не на алгоритм:

def paths(node: Node): Set[String] = {
  def inner(base: String, node: Node): Set[String] = node match {
    case n:Elem =>
      val newBase = base + "/" + n.label
      (Set(newBase) 
        ++ n.child.flatMap(inner(newBase, _))
        ++ n.attributes.map(base + "/@" + _.key))
    case _ => Set.empty
  }
  inner("", node)
}

Я думаю, что это помогает с многословием, проверкой экземпляров и приведением классов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...