【问题标题】:Scala XML validation by XSD and parsing通过 XSD 和解析进行 Scala XML 验证
【发布时间】:2015-01-01 15:00:30
【问题描述】:

我需要通过 xsd 验证 xml 文件,并在可能的情况下解析 xml。我有下一个例子:

import java.io.FileInputStream
import javax.xml.XMLConstants
import javax.xml.parsers.SAXParserFactory
import javax.xml.transform.stream.StreamSource
import javax.xml.validation.SchemaFactory

import org.xml.sax.SAXParseException
import org.xml.sax.helpers.DefaultHandler

import scala.util.Try
import scala.xml.XML

object XMLTup extends App {
  val schema = {
    val factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
    val xsdStream = new FileInputStream("xsd.xsd")
    val schema = factory.newSchema(new StreamSource(xsdStream))
    xsdStream.close()
    schema
  }

  val saxParser = {
    val f = SAXParserFactory.newInstance()
    f.setNamespaceAware(true)
    f.setSchema(schema)
    f.newSAXParser()
  }

  //DOESN'T WORK
  val xml1 = new FileInputStream("xml.xml")
  println {
    Try{XML.withSAXParser(saxParser).load(xml1)}
  }
  xml1.close()

  //WORKS
  val xml2 = new FileInputStream("xml.xml")
  val handler = new DefaultHandler() {
    override def error(ex: SAXParseException)  {
      println("Validation Error!")
    }
  }
  saxParser.parse(xml2, handler)
  xml2.close()
}

当我使用 scala XML(不工作)时,我得到了成功并且没有验证错误,但是下一个代码(工作)我得到了“验证错误”消息。为什么会发生?如何使用 scala XML 类通过 XSD 验证 XML?

【问题讨论】:

    标签: xml scala validation xsd


    【解决方案1】:

    我将 scalaxb 与 sbt 一起使用(我的 xsd 文件位于子项目 genscalaxb 中)。

    添加到项目/plugin.sbt:

    resolvers += Resolver.sonatypeRepo("public")
    
    addSbtPlugin("org.scalaxb" % "sbt-scalaxb" % "1.2.1")
    

    添加到您的 build.sbt(地图是可选的 - 用于自定义包):

    lazy val `genscalaxb` = Project("genscalaxb", file("genscalaxb")).settings(scalaxbSettings: _*).settings(
      packageNames in scalaxb in Compile := Map(new URI("https://github.com/ajozwik/mvn2sbt") -> "pl.jozwik.gen",
        new URI("http://maven.apache.org/POM/4.0.0") -> "org.maven"),
      sourceGenerators in Compile <+= scalaxb in Compile
    )
    

    把你的xsd文件放到:genscalaxb/src/main/xsd

    我在函数中使用,see in github:

     private def handlePomFile(pomXml: File, parent: Option[MavenDependency]) = {
        val xmlFromFile = Try(xml.XML.loadFile(pomXml)) match {
          case Success(pom) => pom
          case Failure(th) =>
            logger.error(s"${pomXml.getAbsolutePath} failed to be parse")
            throw th
        }
        val pomModel = scalaxb.fromXML[org.maven.Model](xmlFromFile)
        createProjectMap(pomXml.getParentFile, pomModel, parent)
      }
    

    xsd 文件是maven-4.0.0.xsd

    Xml 文件 - 是 pom。

    【讨论】:

      【解决方案2】:

      令人惊讶的是,发现 scala XML 使用继承了 FactoryAdapter 的 NoBindingFactoryAdapter 巫婆继承了 DefaultHandler。 DefaultHandler 有下一个方法:

      public void error (SAXParseException e)
          throws SAXException
      {
          // no op
      }
      

      您需要重写此方法来处理 xml 验证的错误消息。一种方法是创建自己的 scala trait XMLLoader 对象,并在必要时覆盖适配器和解析器:

       //NOW, IT WORKS
        val xml1 = new FileInputStream("xml.xml")
        println {
          Try{
            val loader = new XMLLoader[Elem] {
              override def adapter: FactoryAdapter = new NoBindingFactoryAdapter() {
                override def error(e: SAXParseException) = {
                  throw e
                }
              }
      
              override def parser: SAXParser = saxParser
            }
            loader.load(xml1)
          }
        }
        xml1.close()
      

      【讨论】:

        猜你喜欢
        • 2014-07-03
        • 2015-06-28
        • 2013-08-30
        • 1970-01-01
        • 2012-04-13
        • 2013-12-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多