代码之家  ›  专栏  ›  技术社区  ›  waterlooalex

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

  •  10
  • waterlooalex  · 技术社区  · 15 年前

    我编写了一个简单的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 回复  |  直到 14 年前
        1
  •  6
  •   David Crawshaw    15 年前

    下面是一篇博客文章,介绍如何在斯卡拉中使用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
  •  2
  •   Eugene Ryzhikov    15 年前

    我认为你还不能用scala库来完成它。 但是你绝对可以使用Java库。只要谷歌“Java模式验证”,你就会发现很多选项。

        3
  •  2
  •   Horst Dehmer    14 年前

    以下是对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()
        }
    }
    

    应用程序也略有不同:

    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)