【问题标题】:Validating XSD against W3C XML Schema Definition根据 W3C XML 模式定义验证 XSD
【发布时间】:2012-07-26 08:19:58
【问题描述】:

我正在生成一些 XML 模式,并希望确保我们的生成器正在创建有效的 XML 模式文档(不是 XML)。我试图提出验证 XML Schema 文档的代码,但失败得很惨。没想到会这么复杂。

  private void validateXsd( String xsdAsString ) {
    try {
      SAXParserFactory factory = SAXParserFactory.newInstance();
      factory.setValidating(true);
      factory.setNamespaceAware(true);
      factory.setFeature( "http://apache.org/xml/features/validation/schema", true );

      SchemaFactory schemaFactory = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI );

      URL xmlSchemaXSD = this.getClass().getClassLoader().getResource( "com/metamodel/xsd/XMLSchema.xsd" );
      URL xmlSchemaDTD = this.getClass().getClassLoader().getResource( "com/metamodel/xsd/XMLSchema.dtd" );
      URL xmlSchemaDataTypes = this.getClass().getClassLoader().getResource( "com/metamodel/xsd/datatypes.dtd" );

      // requires that XMLSchema.dtd and datatypes.dtd are present in the same directory with the XMLSchema.xsd.
      factory.setSchema( schemaFactory.newSchema( xmlSchemaXSD ) );

      SAXParser parser = factory.newSAXParser();
      // parser.setProperty( "http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema" );

      XMLReader reader = parser.getXMLReader();
      reader.setErrorHandler( new SimpleErrorHandler() );
      reader.parse( new InputSource( IOUtils.toInputStream( xsdAsString ) ) );
    } catch( SAXParseException e ) {
      e.printStackTrace( System.err );
    } catch ( ParserConfigurationException e ) {
      e.printStackTrace( System.err );
    } catch ( SAXException e ) {
      e.printStackTrace( System.err );
    } catch ( IOException e ) {
      e.printStackTrace( System.err );
    }
  }

这段代码非常接近我需要做的,但我收到以下错误。

org.xml.sax.SAXParseException: schema_reference.4: Failed to read schema document 'jar:file:/r:/as4ot/lib/metamodel.jar!/com/metamodel/xsd/XMLSchema.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:236)
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:172)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:382)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:316)
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaError(XSDHandler.java:2245)
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.getSchema(XSDHandler.java:1590)
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.parseSchema(XSDHandler.java:438)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadSchema(XMLSchemaLoader.java:556)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:523)
    at com.sun.org.apache.xerces.internal.jaxp.validation.xs.SchemaFactoryImpl.newSchema(SchemaFactoryImpl.java:206)
    at javax.xml.validation.SchemaFactory.newSchema(SchemaFactory.java:489)
    at javax.xml.validation.SchemaFactory.newSchema(SchemaFactory.java:521)

我在调用 setSchema(uri) 时使用了 URL,以确保 XMLSchema.dtd 和 datatypes.dtd 是相对的,我希望它们可用,但我不确定如何检查。

我猜它不喜欢 XMLSchema.xsd、XMLSchema.dtd 和 datatypes.dtd 捆绑在我的 jar 中并因此由类加载器加载的事实。有没有办法解决这个问题,以便我可以进入下一个障碍,即 org.xml.sax.SAXParseException: src-resolve: Cannot resolve the name 'xml:lang' to a(n) 'attribute declaration' 假设它的行为与我从 jar 外部的目录路径加载 XMLSchema 时的行为相同。

我的目标是:

  • 从 jar 中加载 XMLSchema.xsd,使其与代码整齐地打包。
  • 克服关于 xml:lang 的下一个错误。

希望我没有要求太多!

谢谢, 斯图尔特

【问题讨论】:

    标签: java xml validation xsd sax


    【解决方案1】:

    出于几个原因,我不会使用您描述的方法来验证 XSD,最重要的一个原因是 XSD 作为一种语言很弱,因此它本身并不能捕获完整的规范。因此,您很可能会验证实际上无效的内容。

    对于 XSD 验证,您有专门的处理器; Java有XSOM;关注user guide

    【讨论】:

    • 太好了,我试了一下,效果很好。在决定接受最终答案之前,我想全面评估迈克尔的回复。
    • 最后非常简单:XSOMParser parser = new XSOMParser(); parser.setErrorHandler( .. ); parser.parse( IOUtils.toInputStream( xsdAsString ) ); 虽然我必须确保我使用的是 xsom14.jar,因为我使用的是较旧的 JRE。我正在使用 relaxngDatatype-2.2.jar 。感谢您的帮助!
    【解决方案2】:

    我同意 Petru 的观点,即根据架构文档的架构验证架构并不是一件非常有用的事情,因为它不会检测到架构中的所有错误。确保架构有效的唯一真正方法是将其传递给架构处理器。

    例如,撒克逊人

    Processor p = new Processor(true);
    StreamSource ss = new StreamSource(new File('mySchema.xsd');
    p.getSchemaManager().load(ss);
    

    会告诉你你的架构是否有效。

    【讨论】:

    • 谢谢,虽然我已经尝试过这种方法并且我一直在p.getSchemaManager() 上找到NullPointerException,因为它返回null。我正在使用 saxon9he.jar 并尝试在创建 Processor 对象时将许可版本设置为 false,但没有帮助。
    • 在 Saxon 中进行模式处理,您需要获取 Saxon-EE。
    • 我将前往 XSOM 路线,因为我不打算购买。非常感谢您的帮助,不胜感激!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-05
    • 2017-06-23
    • 2016-07-09
    • 1970-01-01
    • 2013-06-14
    • 2023-03-27
    相关资源
    最近更新 更多