Scala: создание структуры (XML) из списков списков - PullRequest
1 голос
/ 20 сентября 2010

У меня есть структура из Java, список >, содержащий такие элементы, как:

[[ "Node0", "Node00", "Leaf0"],
 [ "Node0", "Node00", "Leaf1"],
 [ "Node1", "Leaf2"],
 [ "Node0", "Leaf3"],
 [ "Node2", "Node20", "Node200", "Leaf4"]]

Что я хочу сделать, это создать структуру XML (с использованием Scala) в самых простыхКстати, заканчивая чем-то вроде ниже.Я мог бы сделать это множеством способов, итерациями, рекурсивными вызовами и т. Д.

Какие-нибудь предложения по компактному удобочитаемому способу решения этой проблемы?

<node> Node0 
      <node> Node00 
            <node> Leaf0 </node>
            <node> Leaf1 </node>
      </node>
      <node> Leaf3 </node>
</node>
<node> Node1
      <node> Leaf2 </node>
</node>
<node> Node2
      <node> Node20
            <node> Node200
                  <node> Leaf4 </node>
            </node>
      </node>
</node>

Ответы [ 2 ]

5 голосов
/ 20 сентября 2010

Попробуйте этот ответ о том, как выводить XML из коллекции в Scala.

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

<node name="Node0">
  <node name="Node00">

или

<node>
  <name>Node0</name>
  <node>
    <name>Node00</name>
    ...
  </node>
</node> 
3 голосов
/ 21 сентября 2010

Хорошо, я сделал снимок. Я также использую атрибут, как и другие. Есть также пара закомментированных строк для версии, которая будет производить элементы с именем после содержимого списка вместо использования атрибутов.

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

import xml._
import transform._

class AddPath(l: List[String]) extends RewriteRule {
  def listToNodes(l: List[String]): Seq[Node] = l match {
    case Nil => Seq.empty
    case first :: rest => 
      <node>{listToNodes(rest)}</node> % Attribute("name", Text(first), Null)
    //case first :: rest => 
      //<node>{listToNodes(rest)}</node> copy (label =  first)
  }

  def transformChild(child: Seq[Node]) = l match {
    case Nil => child
    case first :: rest =>
      child flatMap {
        case elem: Elem if elem.attribute("name") exists (_ contains Text(first)) =>
        //case elem: Elem if elem.label == first =>
          new AddPath(rest) transform elem
        case other => Seq(other)
      }
  }

  def appendToOrTransformChild(child: Seq[Node]) = {
    val newChild = transformChild(child)
    if (newChild == child)
      child ++ listToNodes(l)
    else
      newChild
  }

  override
  def transform(n: Node): Seq[Node] = n match {
    case elem: Elem => elem.copy(child = appendToOrTransformChild(elem.child))
    case other => other
  }
}

После этого все становится действительно просто. Сначала мы создаем список, а затем создаем из него список правил.

val listOfStrings = List(List("Node0", "Node00", "Leaf0"),
                         List("Node0", "Node00", "Leaf1"),
                         List("Node1", "Leaf2"),
                         List("Node0", "Leaf3"),
                         List("Node2", "Node20", "Node200", "Leaf4"))
val listOfAddPaths = listOfStrings map (new AddPath(_))

Далее мы создаем преобразователь правил из этих правил.

val ruleTransformer = new RuleTransformer(listOfAddPaths: _*)

Наконец, мы создаем XML и довольно печатаем его. Обратите внимание, что я добавляю корневой узел. Если вы не хотите этого, просто получите это child. Также обратите внимание, что ruleTransformer вернет Seq[Node] с одним узлом - наш результат.

val results = ruleTransformer(<root/>)
val prettyPrinter = new PrettyPrinter(80, 4)
results foreach { xml =>
  println(prettyPrinter format xml)
}

А на выходе:

<root>
    <node name="Node0">
        <node name="Node00">
            <node name="Leaf0"></node>
            <node name="Leaf1"></node>
        </node>
        <node name="Leaf3"></node>
    </node>
    <node name="Node1">
        <node name="Leaf2"></node>
    </node>
    <node name="Node2">
        <node name="Node20">
            <node name="Node200">
                <node name="Leaf4"></node>
            </node>
        </node>
    </node>
</root>

Выход альтернативной версии:

<root>
    <Node0>
        <Node00>
            <Leaf0></Leaf0>
            <Leaf1></Leaf1>
        </Node00>
        <Leaf3></Leaf3>
    </Node0>
    <Node1>
        <Leaf2></Leaf2>
    </Node1>
    <Node2>
        <Node20>
            <Node200>
                <Leaf4></Leaf4>
            </Node200>
        </Node20>
    </Node2>
</root>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...