如何在jaxb中解组并享受模式validation而不使用显式模式文件

我正在使用jaxb进行应用程序配置

我觉得我正在做一些非常歪曲的事情,我正在寻找一种不需要实际文件或此交易的方法。

正如您在代码I中看到的:

1.从我的JaxbContext(实际上来自我的类​​注释)创建一个模式到一个文件中.2。设置这个模式文件,以便在我解组时允许真正的validation

JAXBContext context = JAXBContext.newInstance(clazz); Schema mySchema = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(schemaFile); jaxbContext.generateSchema(new MySchemaOutputResolver()); // ultimately creates schemaFile Unmarshaller u = m_context.createUnmarshaller(); u.setSchema(mySchema); u.unmarshal(...); 

你们中的任何人都知道如何validationjaxb而不需要创建一个位于我的计算机中的模式文件吗?

我是否需要创建用于validation的模式,当我通过JaxbContect.generateSchema获取它时,它看起来是多余的?

你怎么做到这一点?

关于上面的ekeren解决方案,在单个线程中使用PipedOutputStream / PipedInputStream不是一个好主意,以免溢出缓冲区并导致死锁。 ByteArrayOutputStream / ByteArrayInputStream可以工作,但如果您的JAXB类生成多个模式(在不同的名称空间中),则需要多个StreamSource。

我最终得到了这个:

 JAXBContext jc = JAXBContext.newInstance(Something.class); final List outs = new ArrayList(); jc.generateSchema(new SchemaOutputResolver(){ @Override public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); outs.add(out); StreamResult streamResult = new StreamResult(out); streamResult.setSystemId(""); return streamResult; }}); StreamSource[] sources = new StreamSource[outs.size()]; for (int i=0; i 

我相信你只需要在你的unmarshaller上设置一个ValidationEventHandler 。 像这样的东西:

 public class JAXBValidator extends ValidationEventCollector { @Override public boolean handleEvent(ValidationEvent event) { if (event.getSeverity() == event.ERROR || event.getSeverity() == event.FATAL_ERROR) { ValidationEventLocator locator = event.getLocator(); // change RuntimeException to something more appropriate throw new RuntimeException("XML Validation Exception: " + event.getMessage() + " at row: " + locator.getLineNumber() + " column: " + locator.getColumnNumber()); } return true; } } 

在你的代码中:

 Unmarshaller u = m_context.createUnmarshaller(); u.setEventHandler(new JAXBValidator()); u.unmarshal(...); 

我有确切的问题,并在Apache Axis 2源代码中找到了一个解决方案:

 protected List generateJaxbSchemas(JAXBContext context) throws IOException { final List results = new ArrayList(); context.generateSchema(new SchemaOutputResolver() { @Override public Result createOutput(String ns, String file) throws IOException { DOMResult result = new DOMResult(); result.setSystemId(file); results.add(result); return result; } }); return results; } 

并且在获得表示模式的DOMResults列表之后,您需要将它们转换为DOMSource对象,然后才能将它们提供给模式生成器。 第二步可能如下所示:

 Unmarshaller u = myJAXBContext.createUnmarshaller(); List dsList = new ArrayList(); for(DOMResult domresult : myDomList){ dsList.add(new DOMSource(domresult.getNode())); } String schemaLang = "http://www.w3.org/2001/XMLSchema"; SchemaFactory sFactory = SchemaFactory.newInstance(schemaLang); Schema schema = sFactory.newSchema((DOMSource[]) dsList.toArray(new DOMSource[0])); u.setSchema(schema); 

如果你使用maven使用jaxb2-maven-plugin可以帮到你。 它在生成资源阶段生成模式。