如何使用Scala验证XML文件的模式?

时间:2022-09-08 17:15:40

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

我写了一个简单的scala程序来打开一个XML文件。

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.

有没有办法让scala根据它引用的模式文件验证XML文件?目前我的XML文件不遵循架构,所以我希望在验证时出错。

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

XML文件在根元素中引用这样的模式:

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

The scala code:

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)

3 个解决方案

#1


6  

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

这是一篇博客文章,描述了如何在Scala中使用Java库进行模式验证:

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

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

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

它归结为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


2  

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

我不认为你可以用Scala库做到这一点。但你绝对可以使用Java库。只需谷歌“java架构验证”,你会发现很多选择

#3


2  

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

以下是对2.8.0(或2.8.1)中的次要API更改的修改:

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)

#1


6  

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

这是一篇博客文章,描述了如何在Scala中使用Java库进行模式验证:

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

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

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

它归结为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


2  

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

我不认为你可以用Scala库做到这一点。但你绝对可以使用Java库。只需谷歌“java架构验证”,你会发现很多选择

#3


2  

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

以下是对2.8.0(或2.8.1)中的次要API更改的修改:

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)