Как проверить схему 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)
3 ответов
вот сообщение в блоге, описывающее, как использовать библиотеки 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]
}
}
Я не думаю, что вы можете сделать это еще с библиотеками Scala. Но вы можете определенно использовать библиотеки Java. Просто google "проверка схемы java", и вы найдете много вариантов
вот адаптация к незначительным изменениям 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)