开发者

How does one validate the schema of an XML file using Scala?

开发者 https://www.devze.com 2022-12-09 06:12 出处:网络
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 s

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[Stri开发者_如何转开发ng]) {
    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)


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]
  }
}


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


Here is an adaptation to minor API changes in 2.8.0 (or 2.8.1):

import org.xml.sax.InputSource
import scala.xml.parsing.NoBindingFactoryAdapter
import scala.xml.{TopScope, Elem}
import javax.xml.parsers.{SAXParserFactory, SAXParser}
import javax.xml.validation.Schema

class SchemaAwareFactoryAdapter(schema: Schema) extends NoBindingFactoryAdapter {
    override def loadXML(source: InputSource, parser: SAXParser) = {
        val reader = parser.getXMLReader()
        val handler = schema.newValidatorHandler()
        handler.setContentHandler(this)
        reader.setContentHandler(handler)

        scopeStack.push(TopScope)
        reader.parse(source)
        scopeStack.pop
        rootElem.asInstanceOf[Elem]
    }

    override def parser: SAXParser = {
        val factory = SAXParserFactory.newInstance()
        factory.setNamespaceAware(true)
        factory.setFeature("http://xml.org/sax/features/namespace-prefixes", true)
        factory.newSAXParser()
    }
}

The application is also slightly different:

val factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
val xsdStream = getClass.getResourceAsStream("/foo.xsd")
val schema = factory.newSchema(new StreamSource(stream))
val source = getClass.getResourceAsStream("baz.xml")
val xml = new SchemaAwareFactoryAdapter(schema).load(source)
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号