Scala:结合xml数据树?

时间:2011-10-16 18:18:13

标签: xml scala

我很想知道组合一组包含类似的xml树的最佳方法 数据到单个集合('union'样式)。

我确实实现了一个有效的解决方案,但代码看起来很糟糕而且我有 强烈的直觉,必须有一个更好,更紧凑的方式 实施这个。

我想要做的是在最简单的情况下结合类似的东西:

<fruit> <apple /> <orange /> </fruit>

<fruit> <banana /> </fruit>

要:

<fruit> <apple/> <orange/> <banana/> </fruit>

如何在scala中实现这一点的好主意?

2 个答案:

答案 0 :(得分:1)

val appleAndOrange : Elem = <fruit> <apple/> <orange/> </fruit>

val banana : Elem = <fruit> <banana> </fruit>

你可以做到

val all = appleAndOrange.copy(child = appleAndOrange.child ++ banana.child)

但是,这只是从<fruit>获取标签appleAndOrange,而忽略来自banana的标签,这里恰好相同。同样如果它们不相同,您必须决定您想要的检查和行为。前缀,属性和范围相同。

答案 1 :(得分:1)

这是另一种值得考虑的方法。我们本质上是从字符串构建scala.xml.Elem并使用一些XPath样式查询。

import scala.xml._
def childUnion(parent: String, a: Elem, b: Elem): Elem = {
    val open:String = "<" + parent + ">"
    val close:String = "</" + parent + ">"
    val children = a \\ parent \ "_" ++ b \\ parent \ "_"
    return XML.loadString(open + children + close)
}

首先,我们创建了openclose标记,这些标记只是字符串。然后我们使用一些XPath样式查询来构造children

\\是Elem上的运算符,它返回元素和Elem的所有子序列。

\类似,但它返回了Elem的元素。

"_"是通配符。

为什么不只是\?我根据文档自己搞清楚这一点,但是看看XPath for Java让我相信\\包括整个Elem本身和孩子,而\只包括孩子,所以如果我们{ {1}}我们什么都找不到,因为只传递了<parent><x/></parent> \ "parent"

现在这种方法并不令人敬畏。我们可以做些什么才能让它变得更棒?我们最好使用Scala精彩的<x/>类和Option方法。

foldLeft

这当然有一个甜蜜的好处,就是只使用一个Elem,父母不在场的情况,以及作为参数提供的可变数量的Elem。这是我在提出这个最终方法时运行的一长串例子,

def childUnion(parent: String, a: Elem, b: Elem*): Option[Elem] = {
    val parentElem = a \\ parent

    parentElem.size match {
        case 0 => None // no parent present
        case _ => 
            val children = b.foldLeft(parentElem \ "_")((d,c) => (d ++ (c \\ parent \ "_")))
            val open:String = "<" + parent + ">"
            val close:String = "</" + parent + ">"
            Some(XML.loadString(open + children + close))
    }
}