我正在尝试使用MOXy为多个包中的类定制XML编组和模式生成的命名算法。
我正在关注Eclipse documentation并且可以让它适用于单个班级:
@XmlNameTransformer(com.example.test.NameGenerator.class)
public class Customer
或单个包裹:
@XmlNameTransformer(com.example.test.NameGenerator.class)
package com.example.test;
(外部绑定文件也可以,但是你只能指定每个绑定文件的包)
然而,因为我有跨多个包的对象,我不想为每个包定义转换器。另外,我想动态地这样做(即直到运行时才知道各个包)。
我已经尝试在父包(com.example
)中定义转换器但是这不起作用 - 看起来它需要是带注释类的确切包。
有什么想法吗?
更新 - 更多信息
也许我应该提到我尝试这样做的主要原因所以我可以控制XML / XSD生成 - 最具体地说,我希望复杂类型是大写而不是默认更低(不需要)注释每一个类),比如
@XmlRootElement
public class Test ...
应该生成:
<Test>
...
</Test>
而不是
<test>
...
</test>
从我做过的其他研究中,我发现这样做的唯一方法是使用XmlNameTransformer
。但是,如果还有另一种方式,我正在咆哮错误的树...绝对让我知道!
答案 0 :(得分:1)
扩展Blaise的答案,这是我的实现的样子。这样就可以将变换器用于动态的包集合。
import org.eclipse.persistence.jaxb.metadata.MetadataSourceAdapter;
import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings;
import org.eclipse.persistence.jaxb.xmlmodel.XmlSchema;
public class NameTransformerAdapter extends MetadataSourceAdapter {
private XmlBindings bindings;
/**
* @param packageName Fully qualified package name, like {@code com.example.test}
*/
public NameTransformerAdapter(String packageName) {
bindings = new XmlBindings();
bindings.setPackageName(packageName);
bindings.setXmlNameTransformer(XmlNameTransformer.class.getName());
bindings.setXmlSchema(new XmlSchema()); // this is necessary
}
@Override
public XmlBindings getXmlBindings(Map<String, ?> properties, ClassLoader classLoader) {
return bindings;
}
}
引用的变压器非常简单:
import org.eclipse.persistence.oxm.XMLNameTransformer;
public class XmlNameTransformer implements XMLNameTransformer {
/** Uses capitalized name of class */
public String transformTypeName(String name) {
return name.substring(name.lastIndexOf('.') + 1);
}
public String transformElementName(String name) {
return name;
}
public String transformAttributeName(String name) {
return name;
}
public String transformRootElementName(String name) {
return transformTypeName(name);
}
}
包在运行时确定,并按如下方式进行跟踪:
List<MetadataSource> adapters = new ArrayList<MetadataSource>();
adapters.add(new NameTransformerAdapter(packageName));
最后,可以使用上述适配器获取JAXBContext:
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
private JAXBContext getContext(Class<?>[] classes) throws JAXBException {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, adapters);
return JAXBContextFactory.createContext(classes, properties);
}
答案 1 :(得分:0)
包级别是您可以指定MOXy / JAXB元数据的最大范围。您可以使用XmlNameTransformer
的相同实现,但是您需要为每个要应用它的包指定它。
但是,由于我的对象跨越多个包,我 不想为每个包定义变压器。 另外,我想动态地这样做(即个人 在运行时之前,包都不知道。
您可以以编程方式创建与外部映射文档对应的对象模型。然后,您可以在创建JAXBContext
时传递此实例。