Как проверить схему XML файла с помощью Scala?

Я написал тривиальную программу scala, чтобы открыть файл XML.

Есть ли способ получить scala для проверки XML файла на файл схемы, который он ссылается? В настоящее время мой XML файл не соответствует схеме, поэтому я ожидаю получить ошибки при проверке.

XML файл ссылается на такую ​​схему в корневом элементе:

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

Код scala:

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

Вот сообщение в блоге, в котором описывается использование библиотек Java для проверки схемы в Scala:

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

Это сводится к базовой повторной реализации 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]
  }
}

Ответ 2

Я не думаю, что вы можете сделать это еще с Scala библиотеками. Но вы можете определенно использовать библиотеки Java. Просто Google "java schema validation", и вы найдете множество опций

Ответ 3

Ниже приведена адаптация к незначительным изменениям API в 2.8.0 (или 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()
    }
}

Приложение также немного отличается:

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)