2009-10-26 6 views
10

J'ai écrit un programme de scala trivial pour ouvrir un fichier XML.Comment peut-on valider le schéma d'un fichier XML en utilisant Scala?

Existe-t-il un moyen de faire en sorte que scala valide le fichier XML par rapport au fichier de schéma qu'il référence? Actuellement, mon fichier XML ne suit pas le schéma, donc je m'attends à recevoir des erreurs lors de la validation.

Le fichier XML fait référence le schéma comme celui-ci dans l'élément racine:

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

Le 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) 

Répondre

6

Voici un blog décrivant comment utiliser les bibliothèques Java pour la validation du schéma à Scala:

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

Il se résume à une réimplantation de base de 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

Je ne pense pas que vous pouvez le faire encore avec les bibliothèques Scala. Mais vous pouvez certainement utiliser des bibliothèques Java. Juste Google « validation de schéma java » et vous trouverez beaucoup d'options

2

Voici une adaptation à des modifications mineures de l'API dans 2.8.0 (ou 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() 
    } 
} 

L'application est également légèrement différente:

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

Cette mise en œuvre a une énorme fuite de mémoire –

Questions connexes