我很想知道组合一组包含类似的xml树的最佳方法 数据到单个集合('union'样式)。
我确实实现了一个有效的解决方案,但代码看起来很糟糕而且我有 强烈的直觉,必须有一个更好,更紧凑的方式 实施这个。
我想要做的是在最简单的情况下结合类似的东西:
<fruit> <apple /> <orange /> </fruit>
和
<fruit> <banana /> </fruit>
要:
<fruit> <apple/> <orange/> <banana/> </fruit>
如何在scala中实现这一点的好主意?
答案 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)
}
首先,我们创建了open
和close
标记,这些标记只是字符串。然后我们使用一些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))
}
}