tags:

views:

437

answers:

2

I've written a trivial scala program to open an XML file.

Is there a way to get scala to validate the XML file against the schema file that it references? Currently my XML file doesn't follow the schema, so I'd expect to get errors on validation.

The XML file references the schema like this in the root element:

<items xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="items.xsd">

The scala code:

import scala.xml._

object HelloWorld {
  def main(args: Array[String]) {
    println("Hello, world! " + args.toList)

    val start = System.currentTimeMillis
    val data = XML.loadFile(args(0))
    val stop = System.currentTimeMillis
    Console.println("Took " + (stop-start)/1000.0 + "s to load " + args(0))
  }
}
HelloWorld.main(args)
+1  A: 

I don't think you can do it yet with Scala libraries. But you can definitely use Java libraries. Just google "java schema validation" and you'll find a lot of options

eugener
+4  A: 

Here is a blog post describing how to use the Java libraries for schema validation in Scala:

http://sean8223.blogspot.com/2009/09/xsd-validation-in-scala.html

It boils down to a basic re-implementation of XML.load:

import javax.xml.parsers.SAXParser
import javax.xml.parsers.SAXParserFactory
import javax.xml.validation.Schema
import javax.xml.validation.ValidatorHandler
import org.xml.sax.XMLReader

class SchemaAwareFactoryAdapter(schema:Schema) extends NoBindingFactoryAdapter {

  override def loadXML(source: InputSource): Elem = {
    // create parser
    val parser: SAXParser = try {
      val f = SAXParserFactory.newInstance()
      f.setNamespaceAware(true)
      f.setFeature("http://xml.org/sax/features/namespace-prefixes", true)
      f.newSAXParser()
    } catch {
      case e: Exception =>
        Console.err.println("error: Unable to instantiate parser")
        throw e
    }

    val xr = parser.getXMLReader()
    val vh = schema.newValidatorHandler()
    vh.setContentHandler(this)
    xr.setContentHandler(vh)

    // parse file
    scopeStack.push(TopScope)
    xr.parse(source)
    scopeStack.pop
    return rootElem.asInstanceOf[Elem]
  }
}
David Crawshaw