2012-07-27 56 views
3

我正在生成一些XML模式,並希望確保我們的生成器正在創建有效的XML模式文檔(不是XML)。我試圖想出驗證XML Schema文檔的代碼,但是失敗了。我不認爲這會是複雜的。針對W3C XML模式定義驗證XSD

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當我使用的是URL(URI),以確保XMLSchema.dtd和datatypes.dtd是相對的,我希望他們都可以,但我不確定我怎麼能檢查。

我猜測它不喜歡XMLSchema.xsd,XMLSchema.dtd和datatypes.dtd捆綁在我的jar中,因此被類加載器加載。無論如何要解決這個問題,以便我可以進入我的下一個障礙,即org.xml.sax.SAXParseException:src-resolve:無法將名稱'xml:lang'解析爲(n)'屬性聲明'組件。,假設它的行爲與從jar外的目錄路徑加載XMLSchema時相同。

我的目標是:

  • 負載從罐內,使其整齊地碼打包XMLSchema.xsd。
  • 獲取關於xml:lang的下一個錯誤。

希望我不要問太多!

感謝, 斯圖爾特

回答

3

使用你的一對夫婦的原因描述的方法,我不會驗證一個XSD,最重要的一個是,該XSD作爲一種語言是如此薄弱,本身它不會捕獲完整的規格。所以,最有可能的是,你可能會驗證一些事實上是無效的。

對於XSD驗證,您有專門的處理器; Java有XSOM;請按照user guide

+0

太棒了,我已經給了它一個去,它運作良好。在決定接受最終答案之前,我想充分評估邁克爾的迴應。 – mrswadge 2012-07-30 08:56:22

+1

最後很簡單:'XSOMParser parser = new XSOMParser(); parser.setErrorHandler(..); parser.parse(IOUtils.toInputStream(xsdAsString));'雖然我必須確保我使用** xsom14.jar **,因爲我在舊的JRE上。我正在使用** relaxngDatatype-2.2.jar **。謝謝您的幫助! – mrswadge 2012-07-30 12:05:11

2

我同意Petru的說法,即根據模式文檔的模式驗證模式並不是一件非常有用的事情,因爲它不會檢測到模式中的所有錯誤。確保您的模式有效的唯一方法是將其傳遞給模式處理器。

例如,撒克遜

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

會告訴你,你的模式是否有效。

+0

謝謝,儘管我已經嘗試了這種方法,並且因爲它返回了'null',所以我一直在'p.getSchemaManager()'上找到'NullPointerException'。我正在使用saxon9he.jar,並且在創建'Processor'對象時嘗試將許可版本設置爲'false',但它沒有幫助。 – mrswadge 2012-07-30 08:20:49

+0

對於Saxon中的模式處理,您需要獲取Saxon-EE。 – 2012-07-30 11:07:09

+0

我打算去XSOM路線,因爲我不打算購買。非常感謝您的幫助,非常感謝! – mrswadge 2012-07-30 12:03:20