如何在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可以帮到你。 它在生成资源阶段生成模式。