views:

308

answers:

1

I have a Scala representation of some XML (i.e. a scala.xml.Elem), and I'd like to use it with some of the standard Java XML APIs (specifically SchemaFactory). It looks like converting my Elem to a javax.xml.transform.Source is what I need to do, but I'm not sure. I can see various ways to effectively write out my Elem and read it into something compatible with Java, but I'm wondering if there's a more elegant (and hopefully more efficient) approach?

Scala code:

import java.io.StringReader
import javax.xml.transform.stream.StreamSource
import javax.xml.validation.{Schema, SchemaFactory}
import javax.xml.XMLConstants

val schemaXml = <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
                  <xsd:element name="foo"/>
                </xsd:schema>
val schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

// not possible, but what I want:
// val schema = schemaFactory.newSchema(schemaXml)

// what I'm actually doing at present (ugly)
val schema = schemaFactory.newSchema(new StreamSource(new StringReader(schemaXml.toString)))
+1  A: 

What you want is possible - you just have to gently tell the Scala compiler how to go from scala.xml.Elem to javax.xml.transform.stream.StreamSource by declaring an implicit method.

import java.io.StringReader
import javax.xml.transform.stream.StreamSource
import javax.xml.validation.{Schema, SchemaFactory}
import javax.xml.XMLConstants
import scala.xml.Elem

val schemaXml = <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
                  <xsd:element name="foo"/>
                </xsd:schema>
val schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

implicit def toStreamSource(x:Elem) = new StreamSource(new StringReader(x.toString))

// Very possible, possibly still not any good:
val schema = schemaFactory.newSchema(schemaXml)

It isn't any more efficient, but it sure is prettier once you get the implicit method definition out of the way.

Steven Merrill
Thanks for the response. While it's definitely nicer looking this way, it is still writing the Elem out to a String and reading it back in, which I was hoping to avoid.
overthink
Since alternatives aren't exactly flooding in, I'm going to accept this answer (I've also stuck with this approach in my app). Thanks.
overthink
No problem. I wish I knew of a better answer, but I'm not too familiar with Java. I'm jumping back into the Java ecosystem because of Scala. At least this way your code will be more concise.
Steven Merrill