[英]How generate Java classes from several xsd using JAXB (IntellijIdea)
[英]How to generate multiple, slightly different XSD schemas from one Java model with JAXB?
我有一组相关的Java类,它们可以保存我需要的数据。 下面是我所拥有的简化的类图:
现在,我需要从XML导入数据,并为此生成XSD模式。 问题是我想要几个这样的XSD架构:
我可以使用JAXB(以编程方式)轻松地生成满足nr.1要求的XSD。 但是,对于相同类的nr.2和nr.3,是否有办法做到这一点? 换句话说,似乎我需要JAXB中的“配置文件”之类的东西。
更新:
这是我生成XSD模式的方法:
JAXBContext jc = JAXBContext.newInstance(RootNode.class);
final File baseDir = new File(".");
class MySchemaOutputResolver extends SchemaOutputResolver {
public Result createOutput( String namespaceUri, String suggestedFileName ) throws IOException {
return new StreamResult(new File(baseDir,suggestedFileName));
}
}
jc.generateSchema(new MySchemaOutputResolver());
这不是一个完整的答案,只是一个想法。
您可能使用javax.xml.bind.JAXBContext.generateSchema(SchemaOutputResolver)
方法来生成您的模式,因此您基本上使用了特定的JAXBContext
实例。 该实例是基于类中的注释构建的。 在构建上下文时,将这些注释读入一个组织成模型的模型,然后将其用于所有操作。
因此,要生成不同的架构,您可能需要创建不同的上下文。 您不能根据情况更改批注,但是可以以不同的方式阅读批注。
看看AnnotationReader 。 这就是JAXB RI在幕后用来从Java类加载注释的方式。 您可以创建自己的实现,并在创建JAXBContext时使用它。 这是类似的例子 :
final AnnotationReader<Type, Class, Field, Method> annotationReader = new AnnoxAnnotationReader();
final Map<String, Object> properties = new HashMap<String, Object>();
properties.put(JAXBRIContext.ANNOTATION_READER, annotationReader);
final JAXBContext context = JAXBContext.newInstance(
"org.jvnet.annox.samples.po",
Thread.currentThread().getContextClassLoader(),
properties);
那么编写自己的注释阅读器(考虑您所谓的“配置文件”)怎么样? 您可以发明自己的注释@XmlSchemaProfile(name="foo")
。 然后,注释阅读器将检查此注释是否存在所需的值,然后返回它或将其忽略。 您将能够从相同的Java模型构建不同的上下文-从而根据@XmlSchemaProfile
批注定义的配置文件生成不同的模式。
我找到了适合我的解决方案。 这个想法是将XSD生成的结果输出到XML文档(内存中的DOM)中。 JAXB允许这样做。 此后,您可以按任何需要的方式操作文档,添加或删除部件。
我写了一些过滤器,将白名单或黑名单字段(在XSD中为元素)和类(在XSD中为复杂类型)过滤。 尽管我发现这种方法有很多潜在的问题,但在我看来,它确实起到了作用。 下面是案例2模式的代码:
// This SchemaOutputResolver implementation saves XSD into DOM
static class DOMResultSchemaOutputResolver extends SchemaOutputResolver {
private List<DOMResult> results = new LinkedList<DOMResult>();
@Override
public Result createOutput(String ns, String file) throws IOException {
DOMResult result = new DOMResult();
result.setSystemId(file);
results.add(result);
return result;
}
public Document getDocument() {
return (Document)results.get(0).getNode();
}
public String getFilename() {
return results.get(0).getSystemId();
}
}
// This method serializes the DOM into file
protected void serializeXsdToFile(Document xsdDocument, String filename) throws IOException {
OutputFormat format = new OutputFormat(xsdDocument);
format.setIndenting(true);
FileOutputStream os = new FileOutputStream(filename);
XMLSerializer serializer = new XMLSerializer(os, format);
serializer.serialize(xsdDocument);
}
@Test
public void generateSchema2() throws JAXBException, IOException, XPathExpressionException {
JAXBContext context = JAXBContext.newInstance(RootNode.class);
DOMResultSchemaOutputResolver schemaOutputResolver = new DOMResultSchemaOutputResolver();
context.generateSchema(schemaOutputResolver);
// Do your manipulations here as you want. Below is just an example!
filterXsdDocumentComplexTypes(schemaOutputResolver.getDocument(), asList("childNodeA"), true);
filterXsdDocumentElements(schemaOutputResolver.getDocument(), asList("fieldB"));
serializeXsdToFile(schemaOutputResolver.getDocument(), "xf.xsd");
}
private boolean shouldComplexTypeBeDeleted(String complexTypeName, List<String> complexTypes, boolean whitelist) {
return (whitelist && !complexTypes.contains(complexTypeName)) || (!whitelist && complexTypes.contains(complexTypeName));
}
protected void filterXsdDocumentComplexTypes(Document xsdDocument, List<String> complexTypes, boolean whitelist) throws XPathExpressionException {
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList complexTypeNodes = (NodeList)xPath.evaluate("//*[local-name() = 'complexType']", xsdDocument, XPathConstants.NODESET);
for (int i = 0; i < complexTypeNodes.getLength(); i++) {
Node node = complexTypeNodes.item(i);
Node complexTypeNameNode = node.getAttributes().getNamedItem("name");
if (complexTypeNameNode != null) {
if (shouldComplexTypeBeDeleted(complexTypeNameNode.getNodeValue(), complexTypes, whitelist)) {
node.getParentNode().removeChild(node);
}
}
}
NodeList elements = (NodeList)xPath.evaluate("//*[local-name() = 'element']", xsdDocument, XPathConstants.NODESET);
for (int i = 0; i < elements.getLength(); i++) {
Node node = elements.item(i);
Node typeNameNode = node.getAttributes().getNamedItem("type");
if (typeNameNode != null) {
if (shouldComplexTypeBeDeleted(typeNameNode.getNodeValue(), complexTypes, whitelist) && !typeNameNode.getNodeValue().startsWith("xs")) {
node.getParentNode().removeChild(node);
}
}
}
}
protected void filterXsdDocumentElements(Document xsdDocument, List<String> blacklistedElements) throws XPathExpressionException {
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList elements = (NodeList)xPath.evaluate("//*[local-name() = 'element']", xsdDocument, XPathConstants.NODESET);
for (int i = 0; i < elements.getLength(); i++) {
Node node = elements.item(i);
if (blacklistedElements.contains(node.getAttributes().getNamedItem("name").getNodeValue())) {
node.getParentNode().removeChild(node);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.