2009-10-26 75 views
10

我寫了一個簡單的scala程序來打開一個XML文件。如何使用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) 

回答

6

這裏是一個博客帖子描述瞭如何使用模式驗證的Java庫在斯卡拉:

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庫。只是谷歌的「java架構驗證」,你會發現很多的選擇

2

下面是一個適應次要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) 
+0

此實現具有巨大的內存泄漏 – 2015-11-11 16:55:54