Max
Max

Reputation: 2552

How to write the <?xml> tag using scala.xml and Play Framework

Can anyone tell me how to write the "xml" tag to the output? As expected, loadString() method gets rid of it while loading.

object SitemapController extends Controller {

  def validDeals = Action { implicit request =>
    val xmlStr = "<?xml version="1.0" encoding="UTF-8"?><msg>There's no xml tag</msg>" 
    Ok( scala.xml.XML.loadString(xmlStr) )
  } 
}

What I get beck from the controller is just

<msg>There's no xml tag</msg>

Upvotes: 3

Views: 1252

Answers (2)

senz
senz

Reputation: 2158

Play is very silly in handling XML. M.b. not many used it with? Anyway, here is writeable that form proper xml document, also trims spaces. Just import it in controller.

 object Implicits {    
    implicit def writeableOf_Node(implicit codec: Codec): Writeable[NodeSeq] = {
      Logger.debug(s"Codec: $codec")
      Writeable{ xml => {
        val stringWriter = new StringWriter(1024)
        val node = scala.xml.Utility.trim(xml(0))
        scala.xml.XML.write(stringWriter, node, codec.charset, xmlDecl = true, null)
        val out = codec.encode(stringWriter.toString)
        stringWriter.close()
        out
      }}
    }
    }

Upvotes: 1

Richard Close
Richard Close

Reputation: 1905

OK is a Status, which uses a Writable typeclass to encode the content to bytes (see Status.apply). Looking at the source here, the Writable for xml nodes just calls toString. Basically, instead of a document with an xml declaration, you are just getting a string representation of the root node.

To get the decl, you need to call XML.write() with a java.io.Writer and xmlDecl = true, as well as the other parameters. (I was able to supply a null for the DocType, instead of inventing one).

You could write to a StringWriter and then send that, but I think the most efficient way (especially if your document is large) would be to create an implicit Writable for xml.Node to override the builtin one.

Upvotes: 3

Related Questions