0

Let's say I have the following code:

import scala.xml._

def foo(bar:String) = s"The FOO is $bar"

var xml =
    <a type ={foo("attribute")}>
        {foo("text node")}
    </a>

val txt = "<a>{foo(\"updated\")}</a>"

XML.loadString(txt)

That results in

xml: scala.xml.Elem = <a>{foo(&quot;updated&quot;)}</a>

What is the canonical way to make it

xml: scala.xml.Elem = <a>The FOO is updated</a>

Is it even possible without reflection?

ashawley
  • 4,195
  • 1
  • 27
  • 40
vnfedotov
  • 21
  • 4
  • You can't use the Scala expression in a string. Those are only supported by the compiler with the XML literal syntax. – ashawley Jan 25 '19 at 20:15

2 Answers2

2

You can try

val txt1 = s"<a>${foo("updated")}</a>"
XML.loadString(txt1)

This represent the xml in format as

res0: scala.xml.Elem = <a>The FOO is updated</a>
Chaitanya
  • 3,590
  • 14
  • 33
  • 1
    Thank you for your answer. Unfortunately this won't work if you are getting your arguments in runtime because string interpolation is done by compiler. I should've been more clear that the point of this exercise is to update xml in runtime. – vnfedotov Jan 15 '19 at 14:33
0

I guess it's my own fault of trying to make the question as general as possible. The answer I was looking for was some way of updating XML literals from external storage in runtime.

Best way to do that are template engines. There are several options for Scala:

  • Twirl
  • Scalatags
  • Scalate

For the purpose of my project I've found Scalate to be the best fit. So, answering my own question, it would look something like this:

import scala.xml._
import org.fusesource.scalate._

def foo(bar:String) = s"The FOO is $bar"

val engine = new TemplateEngine
val template = engine.load("test.ssp", List(Binding("foo", "String")))
val str1 = engine.layout("test.ssp",Map("foo"-> foo("bar")))
val str2 = engine.layout("test.ssp",Map("foo"-> foo("updated")))

with template "test.ssp" being simply:

<a>${foo}</a>
vnfedotov
  • 21
  • 4