Reputation: 19040
I'm trying to generate some XML from some nested scala types, e.g.
class Inner(val n:String)
class Outer(val n:String, val i:Seq[Inner])
given Outer(1,[2,3])
, i want to generate <root><item>1</item><item>2</item><item>3</item></root>
(note that Inners values are not nested inside Outers element in the xml). I have this code
object Xmlizer {
def main(args: Array[String]) {
val outers = (1 to 2).map(o => new Outer("outer" + o, List(new Inner("i"))))
val root = <root>
{ outers.map(o => <item>{o.n}</item> { o.i.map (i => <item>{i.n}</item>) } ) }
</root>
println(root)
}
}
This generates a compiler error
error: overloaded method value apply with alternatives:
(f: scala.xml.Node => Boolean)scala.xml.NodeSeq <and>
(i: Int)scala.xml.Node
cannot be applied to (Seq[scala.xml.Elem])
{ outers.map(o => <item>{o.n}</item> { o.i.map (i => <item>{i.n}</item>) } ) }
I have nested comprehensions working where the nested loop is within a pair of elements, and if i simplify to one comprehension that works, e.g.
val root = <root>
{ outers.map(o => <item>{o.n}</item><item>{o.i.head.n}</item> ) }
</root>
so its not like the { } needs to return a single container element, but when i expand Inner to be another comprehension it gives the compiler error. Is there some trick to getting this working, or do i need to somehow flatten the scala data into a single list first?
Upvotes: 1
Views: 109
Reputation: 38045
You should create a flat collection of items:
<root>
{ outers.flatMap(o => <item>{o.n}</item> +: o.i.map{ i => <item>{i.n}</item> } ) }
</root>
// <root><item>outer1</item><item>i</item><item>outer2</item><item>i</item></root>
With <item>{o.n}</item><item>{o.i.head.n}</item>
you are creating a combination of 2 objects of the same type, compiler is smart enough to create it.
But this code:
<item>{o.n}</item> { o.i.map (i => <item>{i.n}</item>) }
actually looks like this:
<item>{o.n}</item>{Seq(<item>{o.i.head.n}</item>)}
You are trying to combine 2 object of completely different types. You should tell to compiler how to combine Node
with Seq[Node]
:
<item>{o.n}</item> +: o.i.map (i => <item>{i.n}</item>)
Upvotes: 1